Java Spring Boot JPA延迟获取不工作

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

我有以下两个域对象Suggestion和UserProfile

它们以一对多关系相互映射。当我使用SpringDataJPA获取所有建议时,我会得到每个建议对象对应的用户对象。即使我将
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());
        }

    };
 }
}