Spring Boot JPA Lazy Fetch无法正常运行

时间:2018-06-30 02:24:18

标签: java spring hibernate spring-boot spring-data-jpa

我有以下两个域对象Recommendations和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时,在对Recommendation实体执行findAll()时,不应获取用户对象(JSON)。

我在这里想念什么?

2 个答案:

答案 0 :(得分:3)

您可以使用@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;

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

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

    };
 }
}

答案 1 :(得分:1)

当您声明fetch = FetchType.LAZY时,意味着休眠将在运行时为此字段创建一个代理。调用此字段的getter时。休眠状态执行另一个选择来获取该对象。 如果出现问题,杰克逊会调用“用户”字段的获取方法(如果您使用rest的话)。 因此,如果您不想使用“用户”,请尝试使用模型映射器框架(推土机映射器是一个很好的框架)。