【发布时间】:2018-12-09 05:00:30
【问题描述】:
我有以下两个域对象 Suggestion 和 UserProfile
它们以一对多的关系相互映射。当我使用 Spring Data JPA 获取所有建议时,我会得到每个建议对象对应的用户对象。即使我将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
}
UserProfile.java
@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
}
以下是获取记录的服务:
@Override
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public List<Suggestion> getAllSuggestion() {
return suggestionRespository.findAll();;
}
建议存储库:
@Repository
public interface SuggestionRespository extends JpaRepository<Suggestion,
Integer> {
public List<Suggestion> findAll();
}
以下是 Application 类:
@EnableTransactionManagement
@SpringBootApplication
public class AngularSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(AngularSpringbootApplication.class, args);
}
}
application.properties:
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 格式)。
我在这里错过了什么?
【问题讨论】:
-
你错过了懒惰的意思。懒惰并不意味着“在加载的建议中存储 null 而不是用户”。这意味着“仅当代码第一次尝试访问此数据时才从数据库加载实际用户数据”,例如使用
suggestion.getUser().getUsername()。另外,不要将 List 转换为 ArrayList。绝对不能保证返回的列表是一个 ArrayList,你的代码不应该关心。你为什么这样做? -
@JBNizet,感谢您的回复。我从“懒惰”获取的意思中理解的是; “在我询问他们何时访问他们的父母之前,不要给我孩子”。那是对的吗?我推荐了this question。另外,谢谢你的建议,我会相应地更新我的问题。我已经更新了
-
没有。这意味着只有当您第一次尝试访问该状态时,才会从数据库中加载子对象的状态,即第一次调用子对象上的方法。
-
再一次,调用 getUser() 不会从数据库中加载用户的状态。 在 getUser() 返回的 User 上调用方法 会做到这一点。为什么你认为延迟加载不起作用?你是怎么得出这个结论的?
-
我不应该得到用户对象这是什么意思?你执行了哪些代码,你期望它做什么,它做了什么?除非该建议未链接到任何用户,否则您将始终在建议中包含一个用户。但是 User 的 state 会被延迟加载。这才是最重要的:避免无用的 SQL 查询。如果您从未对建议的用户调用任何方法,则不会执行查询以从数据库中加载用户数据。
标签: java spring hibernate spring-boot spring-data-jpa