gpt4 book ai didi

jpa - Spring Data JPA 和 NamedEntityGraphs

转载 作者:行者123 更新时间:2023-12-03 06:13:41 25 4
gpt4 key购买 nike

目前,我正在努力解决如何仅获取我需要的数据的问题。 findAll() 方法需要根据调用位置来获取数据。我不想最终为每个实体图编写不同的方法。另外,我会避免调用实体管理器并自己形成(重复的)查询。基本上我想使用 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
}

还有我的 JPARepository

@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) 前缀。 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) 自定义存储库。另一种可能的解决方案是创建自定义查询方法并注入(inject) EntityManager。该解决方案为您的存储库提供了最干净的接口(interface),因为您可以将您的方法命名为有意义的名称,但是添加到代码中以提供解决方案会非常复杂,并且您需要手动获取实体管理器而不是使用 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 方法,以确保我们使用的是具有正确实体图的方法。祝你好运。

来源:

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

关于jpa - Spring Data JPA 和 NamedEntityGraphs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31943989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com