[英]ERROR org.hibernate.LazyInitializationException - could not initialize proxy - no Session
[英]Added @Transactional into a test to avoid org.hibernate.LazyInitializationException no Session error. Why is it needed?
我用@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 {
}
getOne
和findOne
之間的區別在於,即使數據庫中沒有實際的行,第一個也總是返回惰性代理。 惰性代理需要打開的EntityManager
才能進行操作。 但是,由於您的測試方法不在單個事務中運行,因此getOne
方法結束后, EntityManager
將立即關閉。
如果沒有打開EntityManager
,則對該對象的調用將失敗,因為它無法再從數據庫中檢索值。
要解決此問題,請使用findOne
而不是getOne
或者使您的測試方法具有事務性。 但是后者會對您的測試用例產生其他影響(它將從findOne
調用返回相同的對象,因為它還將重用單個EntityManager
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.