我们遇到了类似的问题,并设计了几种前瞻性的解决方案,但对于似乎是一个常见问题,似乎没有一个优雅的解决方案。
1) 前缀。 Data jpa 为方法名称提供多个前缀(find、get...)。一种可能性是对不同的命名图使用不同的前缀。这是最少的工作,但向开发人员隐藏了该方法的含义,并且很有可能因加载错误的实体而导致一些不明显的问题。
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
@EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
User findByUserID(int id);
@EntityGraph(value = "User.membershipYears", type = EntityGraphType.LOAD)
User readByUserId(int id);
}
2) 自定义存储库。另一种可能的解决方案是创建自定义查询方法并注入 EntityManager。该解决方案为您的存储库提供了最干净的接口,因为您可以将您的方法命名为有意义的名称,但是添加到代码中以提供解决方案会非常复杂,而且您需要手动获取实体管理器而不是使用 Spring 魔法。
interface UserRepositoryCustom {
public User findUserWithMembershipYearsById(int id);
}
class UserRepositoryImpl implements UserRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public User findUserWithMembershipYearsById(int id) {
User result = null;
List<User> users = em.createQuery("SELECT u FROM users AS u WHERE u.id = :id", User.class)
.setParameter("id", id)
.setHint("javax.persistence.fetchgraph", em.getEntityGraph("User.membershipYears"))
.getResultList();
if(users.size() >= 0) {
result = users.get(0);
}
return result;
}
}
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
@EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
User findByUserID(int id);
}
3)JPQL。本质上,这只是放弃命名实体图并使用 JPQL 来为您处理连接。我认为不理想。
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
@EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
User findByUserID(int id);
@Query("SELECT u FROM users WHERE u.id=:id JOIN??????????????????????????")
User findUserWithTags(@Param("id") final int id);
}
我们选择了选项 1,因为它是最简单的实现方式,但这确实意味着当我们使用存储库时,我们必须查看 fetch 方法,以确保我们使用的是具有正确实体图的方法。祝你好运。
Sources:
- 使用 Spring 具有不同视图的 JPA EntityGraph
- https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods
我没有足够的声誉来发布我的所有来源。对不起 :(