问题
I annotated a test method with @Transactional to avoid:
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)
I do not know why it is needed and wonder whether my application configuration is correct.
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());
}
}
I even added @EnableTransactionManagement but it makes no difference:
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig {
}
回答1:
The difference between getOne and findOne is that the first always returns a lazy proxy, even if there is no actual row in the database. The lazy proxy needs an open EntityManager to operate on. However as your test method doesn't run in a single transaction the EntityManager will be closed as soon as the getOnemethod ends.
Without an open EntityManager calls on the object will fail as it cannot retrieve the values from the database anymore.
To solve use findOne instead of getOne OR make your test method transactional. The latter however has some other effects on your test-case (it will return the same object from the findOne call as it will also reuse a single EntityManager).
来源:https://stackoverflow.com/questions/56027994/added-transactional-into-a-test-to-avoid-org-hibernate-lazyinitializationexcept