Java Spring Boot JPA延迟获取不工作
我有以下两个域对象Suggestion和UserProfile 它们以一对多关系相互映射。当我使用SpringDataJPA获取所有建议时,我会得到每个建议对象对应的用户对象。即使我将Java Spring Boot JPA延迟获取不工作,java,spring,hibernate,spring-boot,spring-data-jpa,Java,Spring,Hibernate,Spring Boot,Spring Data Jpa,我有以下两个域对象Suggestion和UserProfile 它们以一对多关系相互映射。当我使用SpringDataJPA获取所有建议时,我会得到每个建议对象对应的用户对象。即使我将fetch设置为FetchType.Lazy,也可以观察到这个结果。以下是我的代码: Suggestion.java @Entity @Table(name="suggestion") @JsonIgnoreProperties({"suggestionLikes"}) public class Suggestio
fetch
设置为FetchType.Lazy
,也可以观察到这个结果。以下是我的代码:
Suggestion.java
@Entity
@Table(name="suggestion")
@JsonIgnoreProperties({"suggestionLikes"})
public class Suggestion {
public Suggestion() {
// TODO Auto-generated constructor stub
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="suggestion_id")
private Integer suggestionId;
@Column(name="description")
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="suggestion_by")
private UserProfile user;
//getters and setters
}
@Entity
@Table(name = "user_master")
@JsonIgnoreProperties({"suggestions", "suggestionLikes"})
public class UserProfile implements Serializable {
/**
*
*/
private static final long serialVersionUID = 7400472171878370L;
public UserProfile() {
}
@Id
@NotNull
@Column(name = "username", length = 55)
private String userName;
@NotNull
@Column(name = "password")
private String password;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<Suggestion> suggestions;
//getters and setters
}
UserProfile.java
@Entity
@Table(name="suggestion")
@JsonIgnoreProperties({"suggestionLikes"})
public class Suggestion {
public Suggestion() {
// TODO Auto-generated constructor stub
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="suggestion_id")
private Integer suggestionId;
@Column(name="description")
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="suggestion_by")
private UserProfile user;
//getters and setters
}
@Entity
@Table(name = "user_master")
@JsonIgnoreProperties({"suggestions", "suggestionLikes"})
public class UserProfile implements Serializable {
/**
*
*/
private static final long serialVersionUID = 7400472171878370L;
public UserProfile() {
}
@Id
@NotNull
@Column(name = "username", length = 55)
private String userName;
@NotNull
@Column(name = "password")
private String password;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<Suggestion> suggestions;
//getters and setters
}
应用程序。属性:
@Repository
public interface SuggestionRespository extends JpaRepository<Suggestion,
Integer> {
public List<Suggestion> findAll();
}
spring.datasource.url=jdbc:mysql://localhost:3306/plan_trip
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.properties.hibernate.dialect =
org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update
spring.jackson.serialization.fail-on-empty-beans=false
执行getAllSuggestions()
时收到的响应:
[
{
"suggestionId": 2,
"description": "Germanyi!",
"createdBy": "vinit2",
"createdDate": "2018-06-19T10:38:32.000+0000",
"modifiedBy": "vinit2",
"modifiedDate": "2018-06-19T10:38:32.000+0000",
"user": {
"userName": "vinit2",
"password":
"$2a$10$.hP0sQWpl6qqDKiNTkiu0OciQeHRFnkEbEWcDvnv1HY4QCi2tKo.2",
"firstName": "Vinit2",
"lastName": "Divekar2",
"emailAddress": "vinit@gmail.com",
"createdBy": null,
"modifedBy": null,
"createdDate": "2018-06-04",
"modifiedDate": "2018-06-04",
"isActive": "1",
"handler": {},
"hibernateLazyInitializer": {}
}
},
{
"suggestionId": 1,
"description": "Vasai!",
"createdBy": "vinit1",
"createdDate": "2018-06-19T10:37:38.000+0000",
"modifiedBy": "vinit1",
"modifiedDate": "2018-06-19T10:37:38.000+0000",
"user": {
"userName": "vinit1",
"password": "$2a$10$D0RMSTWu03Jw7wC1/zqFxOOjb0Do24o/4mq2PhDhRUyBrs8bdGvUG",
"firstName": "Vinit1",
"lastName": "Divekar1",
"emailAddress": "vinit@gmail.com",
"createdBy": null,
"modifedBy": null,
"createdDate": "2018-06-04",
"modifiedDate": "2018-06-04",
"isActive": "1",
"handler": {},
"hibernateLazyInitializer": {}
}
}
]
预期答复:
[{
"suggestionId": 2,
"description": "Germanyi!",
"createdBy": "vinit2",
"createdDate": "2018-06-19T10:38:32.000+0000",
"modifiedBy": "vinit2",
"modifiedDate": "2018-06-19T10:38:32.000+0000"
},
{
"suggestionId": 1,
"description": "Vasai!",
"createdBy": "vinit1",
"createdDate": "2018-06-19T10:37:38.000+0000",
"modifiedBy": "vinit1",
"modifiedDate": "2018-06-19T10:37:38.000+0000"
}
]
当我将FetchType
声明为Lazy
时,在建议实体上执行findAll()
时,不应该获取用户对象(JSON)
这里缺少什么?当您声明fetch=FetchType.LAZY时,它意味着hibernate在运行时为该字段创建一个代理。当调用此字段的getter时。hibernate执行另一个select以获取此对象。 如果您遇到问题,“user”字段的getter由Jackson调用(如果您使用rest)。
因此,如果您不想要“用户”,请尝试使用模型映射器框架(dozer mapper是一个很好的框架) 您可以使用@JsonManagedReference&@JsonBackReference来防止jakson进行代理调用。下面的代码可能对您有所帮助
@JsonBackReference
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<Suggestion> suggestions;
@JsonManagedReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "suggestion_by")
private UserProfile user;
你错过了懒惰的含义。lazy并不意味着“在加载的建议中存储null而不是用户”。这意味着“仅当代码首次尝试访问此数据时才从数据库加载实际用户数据”,例如使用
suggestion.getUser().getUsername()
。另外,不要将列表强制转换为ArrayList。绝对不能保证返回的列表是ArrayList,代码也不必在意。你为什么这么做?@JBNizet,谢谢你的回复。我从“懒”的意思理解是;'不要给我孩子,直到我问他们,当我访问他们的父母'。对吗?我提到过。另外,谢谢你的建议,我会相应地更新我的问题。我没有更新。这意味着只有当您第一次尝试访问此状态时,才会从数据库加载子对象的状态,即第一次调用子对象上的方法。同样,调用getUser()不会从数据库加载用户的状态。对getUser()返回的用户调用一个方法就可以做到这一点。为什么您认为延迟加载不起作用?你是怎么得出这个结论的?我不应该得到用户对象这是什么意思?您执行了哪些代码,您希望它做什么,它做了什么?建议中始终包含一个用户,除非该建议未链接到任何用户。但是用户的状态将被延迟加载。重要的是:避免无用的SQL查询。如果您从未对建议的用户调用任何方法,则不会执行任何查询以从数据库加载用户数据。感谢您的回复。但是,我仍然在JSON中获取用户对象。@JsonBackReference可以很好地在JSON中隐藏惰性数据
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
jacksonObjectMapperBuilder.modules(new Hibernate5Module());
}
};
}
}