当前位置: 首页 > 知识库问答 >
问题:

Spring Data JPA和NamedEntityGraphs

淳于知
2023-03-14
@Entity
@Table(name="complaints")
@NamedEntityGraphs({
    @NamedEntityGraph(name="allJoinsButMessages", attributeNodes = {
            @NamedAttributeNode("customer"),
            @NamedAttributeNode("handling_employee"),
            @NamedAttributeNode("genre")
    }),
    @NamedEntityGraph(name="allJoins", attributeNodes = {
            @NamedAttributeNode("customer"),
            @NamedAttributeNode("handling_employee"),
            @NamedAttributeNode("genre"),
            @NamedAttributeNode("complaintMessages")
    }),
    @NamedEntityGraph(name="noJoins", attributeNodes = {

    })
})
public class Complaint implements Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private long id;

    private Timestamp date;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer")
    private User customer;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "handling_employee")
    private User handling_employee;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="genre")
    private Genre genre;

    private boolean closed;

    @OneToMany(mappedBy = "complaint", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<ComplaintMessage> complaintMessages = new ArrayList<ComplaintMessage>();

//getters and setters
}
@Repository
public interface ComplaintRepository extends JpaRepository<Complaint, Long>{

    List<Complaint> findByClosed(boolean closed);

    @EntityGraph(value = "allJoinsButMessages" , type=EntityGraphType.FETCH)
    @Override
    List<Complaint> findAll(Sort sort);
}

共有1个答案

裴畅
2023-03-14

我们遇到了一个类似的问题,并设计了几个潜在的解决方案,但似乎没有一个优雅的解决方案似乎是一个常见的问题。

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)CustomRepository。另一种可能的解决方案是创建自定义查询方法并注入EntityManager。这种解决方案为存储库提供了最干净的接口,因为您可以为方法命名一些有意义的东西,但添加到代码中以提供解决方案是相当复杂的,而且您正在手动获取实体管理器,而不是使用Spring Magic。

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,因为它在实现上最简单,但这确实意味着当我们使用存储库时,我们必须查看获取方法,以确保使用的是具有正确实体图的方法。祝你好运.

资料来源:

    null
 类似资料:
  • 我只想不使用xml,所以我需要非xml替代这些设置。这是我的POM。

  • 我的项目中的三个模型对象(本文末尾的模型和存储库片段)之间确实存在关系。 当我调用时,它会触发三个select查询: (“sql”) (对我来说)那是相当不寻常的行为。在阅读Hibernate文档后,我认为它应该始终使用连接查询。当类中的更改为时,查询没有区别(使用附加选择进行查询),当更改为时,城市类的查询也一样(使用JOIN进行查询)。 当我使用抑制火灾时,有两种选择: 我的目标是在所有情况下

  • 如何使用Spring Rest Controller和Spring Data JPA仅更新从@刚体传递的实体属性? 员工实体: 服务类方法: 请求体: Hibernate更新查询: Spring Data JPA正在尝试将company_id设置为空以进行更新,即使我没有将其传递给请求体?但是如果我从数据库中得到实体,使用employee_id传递,然后如果我试图保存(),那么它的工作正常。 我想

  • 我目前正在开发一个具有核心模块和不同“扩展”模块的应用程序。核心模块包括基于Spring配置类的JPA配置以及一些“基本”实体及其存储库,这些实体和存储库将在“扩展”模块中使用。扩展模块包含额外的实体类和JPARepositories。启动扩展模块的JUnit测试时,我遇到以下错误: 为了做到这一点,我尝试了三种不同的方法: 创建了一个名为coreEntityManager和setPackages

  • SpringDataJpa中 Specification怎样使用in查询 实体类Menu.java如下 想通过roles属性做in查询,代码如下 错误如下: Parameter value [com.appmtce.pojo.entity.role.Role@20f81e2a] did not match expected type [java.util.Collection (n/a)] 我的S

  • 我正在使用100个实体(使用JHipster)设置一个新的Spring Boot API,我的问题是:鉴于我有一组存储库层方法,我希望我的所有存储库都能够调用这些方法。 我已经尝试制作所有接口来扩展('RepositoryQuery'是我默认的自定义接口名称后缀),然后使用特定于实体的类。请注意,所有的类扩展了一个泛型实现类,名为。 请注意,给定正则表达式中的“.*”代表我的持久实体集中的任何实体

  • 我想根据我的输入选择列(列表 我知道要选择不同的特定列,我可以使用@Query("SELECT DISTINCT name OF TABLE"),但是,我想给用户选择他们想要的列的灵活性。列表

  • 我在SQLSerever中有一个数据库表,其中包含一些数据(最高id为360)。 现在,我想使用Spring数据JPA将新记录插入到这个表中。 有没有一种方法可以使新记录的id以增量方式跟随存量数据的id(即361、362等)? 寻找一种不会将我绑定到当前数据库的解决方案(即,不应阻止我将来无缝切换到另一个数据库)