spring-data-jpa报错org.hibernate.LazyInitializationException

spring-data-jpa启动报错:

在使用spring-data-jpa单元测试时getOne()方法报错:
spring-data-jpa报错org.hibernate.LazyInitializationException_第1张图片
查找资料发现是因为“懒加载”导致的;

解决办法1:在实体类上添加注解:@Proxy(lazy = false),不使用懒加载就行了。
package com.wn.domain;

import org.hibernate.annotations.Proxy;

import javax.persistence.*;

@Entity
@Table(name = "customer")
@Proxy(lazy = false) // 不使用懒加载
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Long custId;
    @Column(name = "cust_name")
    private String custName;
    @Column(name = "cust_gender")
    private Boolean custGender;
    @Column(name = "cust_address")
    private String custAddress;
}
解决方法2:在测试方法上加@Transactional注解
package com.wn.test;

import com.wn.dao.CustomerRepository;
import com.wn.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataJpaTest {

    @Autowired
    CustomerRepository repository;

    /**
     * 根据id查询一个
     */
    @Test
    @Transactional
    public void testFindOne() {
        Customer customer = repository.getOne(2L);
        System.out.println(customer);
    }
}
解决方法3:使用findById()方法
package com.wn.test;

import com.wn.dao.CustomerRepository;
import com.wn.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataJpaTest {

    @Autowired
    CustomerRepository repository;

    /**
     * 根据id查询一个
     */
    @Test
    public void testFindOne() {
        // 如果调用方法的返回值为Optional对象则不会报错
        Optional<Customer> optionalCustomer = repository.findById(5L);
        Customer customer = optionalCustomer.get();
        System.out.println(customer);
    }
}

getOne()方法和findById()方法区别:

首先要知道的时spring-data-jpa会帮我们生成dao层接口的代理对象,getOne()方法和findById()最终都会执行到org.springframework.data.jpa.repository.support.SimpleJpaRepository类中,由该类负责调用jpa原始的EntityManager对象的相关方法来执行;

getOne()方法为延迟加载(懒加载),调用的是EntityManager对象的getReference()方法

public T getOne(ID id) {
	Assert.notNull(id, "The given id must not be null!");
    return this.em.getReference(this.getDomainClass(), id);
}

findById()方法是立即加载,调用的EntityManager对象的find()方法

public Optional<T> findById(ID id) {
	Assert.notNull(id, "The given id must not be null!");
	Class<T> domainType = this.getDomainClass();
	if (this.metadata == null) {
		// 调用find()方法
	    return Optional.ofNullable(this.em.find(domainType, id));
	} else {
	    LockModeType type = this.metadata.getLockModeType();
	    Map<String, Object> hints = this.getQueryHints().withFetchGraphs(this.em).asMap();
	    // 调用find()方法
	    return Optional.ofNullable(type == null ? this.em.find(domainType, id, hints) : this.em.find(domainType, id, type, hints));
	}
}

你可能感兴趣的:(spring-data-jpa报错org.hibernate.LazyInitializationException)