我用@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 {
}
答案 0 :(得分:3)
getOne
和findOne
之间的区别在于,即使数据库中没有实际的行,第一个也总是返回惰性代理。惰性代理需要打开的EntityManager
才能进行操作。但是,由于您的测试方法不在单个事务中运行,因此EntityManager
方法一结束,getOne
将被关闭。
在对象上没有打开EntityManager
的调用将失败,因为它不再能够从数据库中检索值。
要解决此问题,请使用findOne
而不是getOne
或将测试方法变为事务性。然而,后者会对您的测试用例产生其他影响(它会从findOne
调用返回相同的对象,因为它还会重用单个EntityManager
)。