Spring Boot JPA Lazy Fetch 不起作用 [英] Spring Boot JPA Lazy Fetch is not working

查看:36
本文介绍了Spring Boot JPA Lazy Fetch 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

它们以一对多的关系相互映射.当我使用 Spring Data JPA 获取所有建议时,我会使用每个建议对象获得相应的用户对象.即使我将 fetch 设置为 FetchType.Lazy,也会观察到这个结果.以下是我的代码:

Suggestion.java

@Entity@Table(name="建议")@JsonIgnoreProperties({"suggestionLikes"})公开课建议{公共建议(){//TODO 自动生成的构造函数存根}@ID@GeneratedValue(策略=GenerationType.IDENTITY)@Column(name="suggestion_id")私人整数建议Id;@Column(名称=说明")私人字符串描述;@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name="suggestion_by")私人 UserProfile 用户;//getter 和 setter}

UserProfile.java

@Entity@Table(name = "user_master")@JsonIgnoreProperties({"suggestions", "suggestionLikes"})公共类 UserProfile 实现了 Serializable {/****/私有静态最终长serialVersionUID = 7400472171878370L;公共用户配置文件(){}@ID@NotNull@Column(name = "用户名", 长度 = 55)私人字符串用户名;@NotNull@Column(name = "密码")私人字符串密码;@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)私人设置<建议>建议;//getter 和 setter}

以下是获取记录的服务:

@Override@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)公开列表<建议>getAllSuggestion() {返回建议Respository.findAll();;}

建议库:

@Repository公共接口 SuggestionRespository 扩展 JpaRepository{公开列表<建议>找到所有();}

以下是 Application 类:

@EnableTransactionManagement@SpringBootApplication公共类 AngularSpringbootApplication {公共静态无效主(字符串 [] args){SpringApplication.run(AngularSpringbootApplication.class, args);}}

application.properties:

spring.datasource.url=jdbc:mysql://localhost:3306/plan_tripspring.datasource.username=rootspring.datasource.password=rootspring.jpa.properties.hibernate.dialect =org.hibernate.dialect.MySQL5InnoDBDialectspring.jpa.hibernate.ddl-auto = 更新spring.jackson.serialization.fail-on-empty-beans=false

执行 getAllSuggestions() 时收到的响应:

<预><代码>[{建议ID":2,"description": "德语!","createdBy": "vinit2","createdDate": "2018-06-19T10:38:32.000+0000",修改者":vinit2","修改日期": "2018-06-19T10:38:32.000+0000",用户":{"userName": "vinit2",密码":"$2a$10$.hP0sQWpl6qqDKiNTkiu0OciQeHRFnkEbEWcDvnv1HY4QCi2tKo.2","firstName": "Vinit2","lastName": "Divekar2","emailAddress": "vinit@gmail.com",createdBy":空,修改者":空,"createdDate": "2018-06-04","修改日期": "2018-06-04","isActive": "1",处理程序":{},hibernateLazyInitializer":{}}},{建议ID":1,"description": "瓦赛!","createdBy": "vinit1","createdDate": "2018-06-19T10:37:38.000+0000",修改者":vinit1","修改日期": "2018-06-19T10:37:38.000+0000",用户":{"userName": "vinit1","密码": "$2a$10$D0RMSTWu03Jw7wC1/zqFxOOjb0Do24o/4mq2PhDhRUyBrs8bdGvUG","firstName": "Vinit1","lastName": "Divekar1","emailAddress": "vinit@gmail.com",createdBy":空,修改者":空,"createdDate": "2018-06-04","修改日期": "2018-06-04","isActive": "1",处理程序":{},hibernateLazyInitializer":{}}}

]

预期响应:

<代码>[{建议ID":2,"description": "德语!","createdBy": "vinit2","createdDate": "2018-06-19T10:38:32.000+0000",修改者":vinit2",修改日期":2018-06-19T10:38:32.000+0000"},{建议ID":1,"description": "瓦赛!","createdBy": "vinit1","createdDate": "2018-06-19T10:37:38.000+0000",修改者":vinit1",修改日期":2018-06-19T10:37:38.000+0000"}]

当我将 FetchType 声明为 Lazy 时,当我在 Suggestion 上执行 findAll() 时,我不应该获取 User 对象(以 JSON 格式)实体.

我在这里遗漏了什么?

解决方案

您可以使用@JsonManagedReference &@JsonBackReference 以防止 jakson 调用代理.以下代码可能对您有所帮助.

@JsonBackReference@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)私人设置<建议>建议;@JsonManagedReference@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "suggestion_by")私人 UserProfile 用户;

添加以下依赖项,根据你的休眠更改版本

<依赖><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-hibernate5</artifactId></依赖>

最后添加一个新的配置

@Configuration公共类 JacksonConfig {@豆角,扁豆公共 Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() {返回新的 Jackson2ObjectMapperBuilderCustomizer() {@覆盖公共无效定制(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder){jacksonObjectMapperBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);jacksonObjectMapperBuilder.modules(new Hibernate5Module());}};}}

I have following two domain objects Suggestion and UserProfile

They are mapped with each other in one to many relationship. When I fetch all suggestions using Spring Data JPA, I get corresponding user object with each suggestion objects. This result is observed even when I have set fetch as FetchType.Lazy. Following is my code:

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
}

Following is the service which fetches the records:

@Override
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public List<Suggestion> getAllSuggestion() {
    return suggestionRespository.findAll();;
}

SuggestionRepository:

@Repository
public interface SuggestionRespository extends JpaRepository<Suggestion, 
Integer> {

    public List<Suggestion> findAll();
}

Following is the Application class:

@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

Response received when getAllSuggestions() is executed:

[
{
    "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": {}
    }
}

]

Expected response:

[{
    "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"
}
]

When I have declared FetchType as Lazy, I should not get User objects (in JSON) when I execute findAll()on Suggestion entity.

What am I missing here?

解决方案

You can use @JsonManagedReference & @JsonBackReference to prevent proxy call by jakson. Following code may help you.

@JsonBackReference
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<Suggestion> suggestions;

@JsonManagedReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "suggestion_by")
private UserProfile user;

Add the following dependency, change version according to your hibernate

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>

and finally add a new config

@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());
        }

    };
 }
}

这篇关于Spring Boot JPA Lazy Fetch 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆