惰性加载在使用hibernate的JPA中不起作用
我在spring boot应用程序中使用JPA和hibernate。每当我尝试使用jpa方法获取enities时,它都会返回实体以及其中存在的所有关联。我希望按需获取相关实体(延迟加载),因此我在域类中提供了fetch=FetchType.lazy。但它仍然返回所有条目 代码如下: Case.java惰性加载在使用hibernate的JPA中不起作用,hibernate,jpa,spring-data-jpa,lazy-loading,mapstruct,Hibernate,Jpa,Spring Data Jpa,Lazy Loading,Mapstruct,我在spring boot应用程序中使用JPA和hibernate。每当我尝试使用jpa方法获取enities时,它都会返回实体以及其中存在的所有关联。我希望按需获取相关实体(延迟加载),因此我在域类中提供了fetch=FetchType.lazy。但它仍然返回所有条目 代码如下: Case.java @Entity @Table(name="smss_case") public class Case implements Serializable { /**
@Entity
@Table(name="smss_case")
public class Case implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2608745044895898119L;
@Id
@Column(name = "case_id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer caseId;
@Column( name="case_title" )
private String caseTitle;
@JsonManagedReference
@OneToMany(mappedBy="smmsCase", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Task> tasks;
}
}
@Entity
@Table(name="task_prop")
public class Task implements Serializable {
/**
*
*/
private static final long serialVersionUID = -483515808714392369L;
@Id
@Column(name = "task_id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer taskId;
@Column(name="task_title")
private String taskTitle;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn( name="case_id", nullable=false)
private Case smmsCase;
// getters and setters
}
public Case getCases(Integer id) {
return dao.findById(1).get();
}
public interface ServiceDao extends JpaRepository<Case, Integer>{
}
Service.java
@Entity
@Table(name="smss_case")
public class Case implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2608745044895898119L;
@Id
@Column(name = "case_id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer caseId;
@Column( name="case_title" )
private String caseTitle;
@JsonManagedReference
@OneToMany(mappedBy="smmsCase", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Task> tasks;
}
}
@Entity
@Table(name="task_prop")
public class Task implements Serializable {
/**
*
*/
private static final long serialVersionUID = -483515808714392369L;
@Id
@Column(name = "task_id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer taskId;
@Column(name="task_title")
private String taskTitle;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn( name="case_id", nullable=false)
private Case smmsCase;
// getters and setters
}
public Case getCases(Integer id) {
return dao.findById(1).get();
}
public interface ServiceDao extends JpaRepository<Case, Integer>{
}
Dao.java
@Entity
@Table(name="smss_case")
public class Case implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2608745044895898119L;
@Id
@Column(name = "case_id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer caseId;
@Column( name="case_title" )
private String caseTitle;
@JsonManagedReference
@OneToMany(mappedBy="smmsCase", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Set<Task> tasks;
}
}
@Entity
@Table(name="task_prop")
public class Task implements Serializable {
/**
*
*/
private static final long serialVersionUID = -483515808714392369L;
@Id
@Column(name = "task_id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer taskId;
@Column(name="task_title")
private String taskTitle;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn( name="case_id", nullable=false)
private Case smmsCase;
// getters and setters
}
public Case getCases(Integer id) {
return dao.findById(1).get();
}
public interface ServiceDao extends JpaRepository<Case, Integer>{
}
公共接口服务DAO扩展了JpaRepository{
}
{“caseId”:1, “案例名称”:“人体工程学”, “任务”:[
{
“任务ID”:1, “任务标题”:“ca” }, {
“任务ID”:2, “任务标题”:“危险” }, {
“任务ID”:3, “任务标题”:“补救措施” } ] } 任何帮助都将不胜感激
谢谢 很难调查,但我在使用时遇到了这个问题,在这个过程中,它调用了lazy-loaded属性的getter。当我在映射之前使用mapstrct
@时,问题得到了解决
@Mapper
public interface HibernateAwareMapper {
@BeforeMapping
default <T> Set<T> fixLazyLoadingSet(Collection<?> c, @TargetType Class<?> targetType) {
if (!Util.wasInitialized(c)) {
return Collections.emptySet();
}
return null;
}
@BeforeMapping
default <T> List<T> fixLazyLoadingList(Collection<?> c, @TargetType Class<?> targetType) {
if (!Util.wasInitialized(c)) {
return Collections.emptyList();
}
return null;
}
class Util {
static boolean wasInitialized(Object c) {
if (!(c instanceof PersistentCollection)) {
return true;
}
PersistentCollection pc = (PersistentCollection) c;
return pc.wasInitialized();
}
}
}
@Mapper
公共接口HibernateAwareMapper{
@制图前
默认设置fixLazyLoadingSet(集合c,@TargetType类TargetType){
如果(!Util.wasInitialized(c)){
返回集合;
}
返回null;
}
@制图前
默认列表fixLazyLoadingList(集合c,@TargetType类TargetType){
如果(!Util.wasInitialized(c)){
返回集合。emptyList();
}
返回null;
}
类Util{
静态布尔值已初始化(对象c){
if(!(PersistentCollection的c实例)){
返回true;
}
PersistentCollection pc=(PersistentCollection)c;
返回pc.wasInitialized();
}
}
}
是什么让你认为延迟加载不起作用?我猜:您正在将一个案例序列化为JSON,您可以在JSON中看到它的任务。延迟加载并不意味着“不加载”。这意味着当某个东西(比如JSON序列化程序)调用任务集的一个方法(对它们进行序列化)时,JPA执行查询以加载任务。延迟加载工作正常。你只是不明白这是什么意思。顺便说一句,在OneToMany上设置fetch=LAZY是没有用的,因为这是默认值。@JB Nizet,谢谢你的回答。我仍然感到困惑。在我的服务中,我没有调用任务集的任何方法。仍然是getCases()我的服务中的方法正在加载所有相关的任务。请告诉我这里出了什么问题。谢谢!“当某些东西(如JSON序列化程序)调用任务集的方法(以序列化它们)时”“.JSON序列化不是靠魔法实现的。JSON序列化程序遍历对象的所有属性以获取它们的值并将它们转换为JSON。如果它们是一个集合(与您的任务集类似),它将使用迭代器()方法在集合中进行迭代。这会触发延迟加载。你能分享你的控制器代码吗?您是直接返回实体还是返回表示实体的dto?这可能是因为您返回了实体本身,而序列化程序在序列化时调用了相关模型。@JB Nizet,非常感谢!!你是对的。延迟加载实际上正在工作,但当我尝试从API返回对象时,它正在调用关联的实体。@Emre Savcı,谢谢你的回复,我成功了。如上所述,当控制器返回实体时,对象到json序列化将触发关联。为此,我配置了MappingJackson2HttpMessageConverter。(参考资料:)