Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring数据JPA和NamedEntityGraphs_Jpa_Fetch_Spring Data Jpa_Entitygraph - Fatal编程技术网

Spring数据JPA和NamedEntityGraphs

Spring数据JPA和NamedEntityGraphs,jpa,fetch,spring-data-jpa,entitygraph,Jpa,Fetch,Spring Data Jpa,Entitygraph,目前我正在努力只获取我需要的数据。findAll()方法需要根据调用它的位置来获取数据。 我不想为每个实体图编写不同的方法。 此外,我会避免调用EntityManager并自己形成(重复的)查询。 基本上,我想使用内置findAll方法,但我喜欢实体图。有机会吗 @Entity @Table(name="complaints") @NamedEntityGraphs({ @NamedEntityGraph(name="allJoinsButMessages", attributeNode

目前我正在努力只获取我需要的数据。findAll()方法需要根据调用它的位置来获取数据。 我不想为每个实体图编写不同的方法。 此外,我会避免调用EntityManager并自己形成(重复的)查询。 基本上,我想使用内置findAll方法,但我喜欢实体图。有机会吗

@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
}
@实体
@表(name=“投诉”)
@姓名识别图({
@NamedEntityGraph(name=“allJoinsButMessages”,attributeNodes={
@名称三方(“客户”),
@名称三方(“处理员工”),
@命名为“类型”
}),
@NamedEntityGraph(name=“allJoins”,attributeNodes={
@名称三方(“客户”),
@名称三方(“处理员工”),
@命名为“流派”,
@NamedAttributeNode(“投诉信息”)
}),
@NamedEntityGraph(name=“noJoins”,attributeNodes={
})
})
公共类实现了可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@生成值
私人长id;
私有时间戳日期;
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“客户”)
私人用户客户;
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“处理员工”)
私人用户处理(u)员工;;
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“genre”)
私人体裁;
私有布尔闭;
@OneToMany(mappedBy=“投诉”,fetch=FetchType.LAZY,cascade=CascadeType.ALL)
private List complaintMessages=new ArrayList();
//接球手和接球手
}
还有我的JPA假设

@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);
}
@存储库
公共接口投诉存储库扩展了JpaRepository{
列表findByClosed(布尔闭合);
@EntityGraph(value=“allJoinsButMessages”,type=EntityGraphType.FETCH)
@凌驾
列表findAll(排序);
}

我们遇到了一个类似的问题,并设计了几个可能的解决方案,但对于一个常见的问题,似乎没有一个优雅的解决方案

1) 前缀。数据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);
}
@存储库
@交易的
公共接口UserRepository扩展了Crudepository、UserRepositoryCustom{
@EntityGraph(value=“User.membershipYearsAndPreferences”,type=EntityGraphType.LOAD)
用户findByUserID(int-id);
@EntityGraph(value=“User.membershipYears”,type=EntityGraphType.LOAD)
用户readByUserId(int-id);
}
2) 自定义存储库。另一种可能的解决方案是创建自定义查询方法并注入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);
}
interface UserRepositoryCustom{
公共用户findUserWithMembershipYearsById(int-id);
}
类UserRepositoryImpl实现UserRepositoryCustom{
@持久上下文
私人实体管理者;
@凌驾
公共用户findUserWithMembershipYearsById(int id){
用户结果=null;
List users=em.createQuery(“从用户中选择u作为u,其中u.id=:id”,User.class)
.setParameter(“id”,id)
.setHint(“javax.persistence.fetchgraph”,em.getEntityGraph(“User.membershipYears”))
.getResultList();
如果(users.size()>=0){
结果=用户。获取(0);
}
返回结果;
}
}
@存储库
@交易的
公共接口UserRepository扩展了Crudepository、UserRepositoryCustom{
@EntityGraph(value=“User.membershipYearsAndPreferences”,type=EntityGraphType.LOAD)
用户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);
}
@存储库
@交易的
公共接口UserRepository扩展了Crudepository、UserRepositoryCustom{
@EntityGraph(value=“User.membershipYearsAndPreferences”,type=EntityGraphType.LOAD)
用户findByUserID(int-id);
@查询(“从用户中选择u,其中u.id=:id JOIN?????”)
用户findUserWithTags(@Param(“id”)最终int-id);
}
我们选择了选项1,因为它是实现中最简单的,但这确实意味着当我们使用存储库时,我们必须查看获取方法,以确保我们使用的是具有正确实体图的方法。祝你好运

资料来源:


我没有足够的声誉来发布我所有的消息来源。抱歉:(

@EntityGraph
@Query

@Repository
public interface ComplaintRepository extends JpaRepository<Complaint, Long>{

   @EntityGraph(value = "allJoinsButMessages" , type=EntityGraphType.FETCH)
   @Query("SELECT c FROM Complaint ORDER BY ..")
   @Override
   List<Complaint> findAllJoinsButMessages();

   @EntityGraph(value = "allJoins" , type=EntityGraphType.FETCH)
   @Query("SELECT c FROM Complaint ORDER BY ..")
   @Override
   List<Complaint> findAllJoin();

   ...
@存储库
公共接口投诉存储库扩展了JpaRepository{
@EntityGraph(value=“allJoinsButMessages”,type=EntityGraphType.FETCH)
@查询(“根据……从投诉单中选择c”)
@凌驾
列出findAllJoinsButMessages();
@EntityGraph(value=“allJoins”,type=EntityGraphType.FETCH)
@查询(“根据……从投诉单中选择c”)
@凌驾
列出findAllJoin();
...

}

我们也遇到了同样的问题,并构建了一个Spring数据JPA扩展来解决这个问题:

此扩展允许将命名或动态构建的EntityGraph作为任何存储库方法的参数传递

通过此扩展,您可以立即使用此方法:

List<Complaint> findAll(Sort sort, EntityGraph entityGraph);
List findAll(排序、EntityGraph、EntityGraph);
并且能够用Enti调用它
@EntityGraph(value = "fetch.Profile.Address.record", type = EntityGraphType.LOAD)
 Employee getProfileAddressRecordById(long id);
@NamedEntityGraph(name="all.Customer.handling_employee.genre", attributeNodes = {
        @NamedAttributeNode("customer"),
        @NamedAttributeNode("handling_employee"),
        @NamedAttributeNode("genre")
})
@EntityGraph(value = "all.Customer.handling_employee.genre" , type=EntityGraphType.FETCH)
 findAllCustomerHandlingEmployeeGenre
interface UserRepository : PagingAndSortingRepository<UserModel, Long> {
    @EntityGraph(attributePaths = arrayOf("address"))
    fun findAnythingGoesHereById(id: Long): Optional<UserModel>

    @EntityGraph(attributePaths = arrayOf("address"))
    fun findAllAnythingGoesHereBy(pageable: Pageable): Page<UserModel>
}

@Repository
public interface ComplaintRepository extends JpaRepository<Complaint, Long>{

    List<Complaint> findByClosed(boolean closed);

    @EntityGraph(attributePaths = {"customer", "genre", "handling_employee" }, type=EntityGraphType.FETCH)
    @Override
    List<Complaint> findAll(Sort sort);

    @EntityGraph(attributePaths = {"customer", "genre", "handling_employee", "messages" }, type=EntityGraphType.FETCH)
    default List<Complaint> queryAll(Sort sort){
      return findAll(sort);
    }
}