有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将@Transactional添加到测试中,以避免组织。冬眠LazyInitializationException无会话错误。为什么需要它?

我用@Transactional注释了一个测试方法,以避免:


org.hibernate.LazyInitializationException: could not initialize proxy [com....OrderEntity#6def569a-ebf2-473e-b1b1-8b67e62fd17d] - no Session

    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
    at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
    at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
    at com...orders.OrderEntity$HibernateProxy$wwLGAOuY.getDescription(Unknown Source)

我不知道为什么需要它,不知道我的应用程序配置是否正确

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
import java.util.UUID;

@Entity
@Table(name = "orders")
@Getter
@Setter
public class OrderEntity {

    @Id
    @GeneratedValue
    private UUID uid;
    private Date created;
    private Date updated;
    private String description;

}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository
public interface OrderRepository extends JpaRepository<OrderEntity, UUID> {

    List<OrderEntity> findByDescription(String description);
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

@Service
@Transactional
public class OrderService
{

    private OrderRepository repository;

    @Autowired
    public OrderService(OrderRepository repository) {
        this.repository = repository;
    }

    public List<OrderEntity> findAll() {
        return repository.findAll();
    }

    public OrderEntity save(OrderEntity order) {
        return repository.save(order);
    }

    public OrderEntity getOne(UUID uid) {
        return repository.getOne(uid);
    }
}

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.Assert.assertEquals;

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderServiceTest {

    @Autowired
    private OrderService service;

    @Test
    @Transactional
    public void testSave() {

        OrderEntity order = new OrderEntity();
        order.setDescription("Order description");

        OrderEntity saved = service.save(order);
        System.out.println(saved.getDescription());

        OrderEntity persisted = service.getOne(saved.getUid());
        // throws LazyInitializationException without @Transactional
        System.out.println(persisted.getDescription()); 

        assertEquals(persisted.getDescription(), order.getDescription());
    }
}

我甚至添加了@EnableTransactionManagement,但没有什么区别:

import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig {
}

共 (1) 个答案

  1. # 1 楼答案

    getOnefindOne之间的区别在于,第一个始终返回一个惰性代理,即使数据库中没有实际的行。惰性代理需要一个开放的EntityManager来操作。但是,由于您的测试方法不在单个事务中运行,EntityManager将在getOne方法结束后立即关闭

    如果没有打开EntityManager,对对象的调用将失败,因为它无法再从数据库中检索值

    要解决此问题,请使用findOne而不是getOne或使测试方法具有事务性。但是,后者对测试用例有一些其他影响(它将从findOne调用返回相同的对象,因为它还将重用单个EntityManager