![](/img/trans.png)
[英]LazyInitializationException when using join in CrudRepository
[英]Hibernate LazyInitializationException using Spring CrudRepository
我总是得到例外:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.knapp.vk.domain.Business.businessCategorySet, could not initialize proxy - no Session
我不想把fetch设置为渴望。 什么是其他好的解决方案?
商业实体类:
@Entity
public class Business
{
@Id
@GeneratedValue
private int pk;
@ManyToMany
private Set<BusinessCategory> businessCategorySet = new HashSet<BusinessCategory>();
...
}
BusinessRepository接口:
import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public interface BusinessRepository extends CrudRepository<Business, Integer>
{
}
配置:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableJpaRepositories(basePackages = "com.knapp.vk.repositorynew")
@EnableTransactionManagement
public class JPAConfiguration
{
@Bean
public EntityManagerFactory entityManagerFactory() throws SQLException
{
return Persistence.createEntityManagerFactory("standardManager");
}
@Bean
public EntityManager entityManager(EntityManagerFactory entityManagerFactory)
{
return entityManagerFactory.createEntityManager();
}
@Bean
public PlatformTransactionManager transactionManager() throws SQLException
{
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator()
{
return new HibernateExceptionTranslator();
}
}
所以你可以通过在Service中初始化businessCategoruSet来实现它,而不是在Repository中使用@Transactional
而是在Service中使用它。 让我们在存储库中编写一些像id或业务列表获取业务的方法,并从服务中访问该方法。
@Transactional
public Class BusinessService{
@resource
BusinessRepository businessRepository;
public Business getBusiness(){
Business business = businessRepository.getBusiness();
//Here you should initialize BusinessCategorySet
Object object = business.getBusinessCategoriesSet().size();
}
}
有关@Transactional
更多详细信息, 请参阅此链接
您还可以在存储库中添加方法:
@Transactional(readOnly = true)
public List<Business> findAllEagerly() {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Business> query = builder.createQuery(Business.class);
Root<Business> root = query.from(Business.class);
root.fetch(Business_.businessCategorySet);
return em.createQuery(query).getResultList();
}
或者更容易在JpaRepository中使用@Query:
@Query("SELECT b FROM Business b JOIN FETCH b.businessCategorySet")
public List<Business> findAll();
我认为好的解决方案是使用@NamedEntityGraph
@Entity
@NamedEntityGraph(name = "Business.detail",
attributeNodes = @NamedAttributeNode("businessCategorySet"))
public class Business {...}
并在存储库中
public interface BusinessRepository extends CrudRepository<Business, Integer> {
@EntityGraph(value = "Business.detail", type = EntityGraphType.LOAD)
List<Business> findAll();
}
也可以看看:
Hibernate会话的范围在事务中。 因此,如果您在服务层开始交易,您的休眠会话将可用到服务层。 如果你在另一个对象中调用任何对象,例如(business.getBusinessCategorySet())需要加载延迟,将导致抛出“org.hibernate.LazyInitializationException”。 要解决此问题,您有两个解决方案1)在服务层2中加载所有相关对象。使用Open Session In View(OSIV)配置,它将使您的休眠会话打开,直到查看图层。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.