问题
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 getOne
method 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