2014-11-24 74 views
2

我总是得到异常:Hibernate的LazyInitializationException中使用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 

我不希望设置取跃跃欲试。其他好的解决方案是什么?

业务实体类:

@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(); 
    } 
} 

回答

4

所以,你可以通过在服务初始化businessCategoruSet因此而不是使用@Transactional在仓库使用它在服务做到这一点。 让写像库通过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(); 
    } 
} 

@TransactionalRefer this link

1

Hibernate会话都有其交易范围之内。所以,如果你正在服务层开始你的事务,你的hibernate会话将可用,直到服务层。如果您正在调用另一个对象内的任何对象,例如(business.getBusinessCategorySet()),其需要被加载懒惰,将导致抛出“org.hibernate.LazyInitializationException”。要解决此问题,你有两个解决方案 1)负载服务层 2)使用打开会话视图(OSIV)配置中的所有相关对象,它会使你的冬眠会议开到视图层。

4

您也可以在资源库中添加方法有关详细信息:

@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(); 
} 

参见:

Custom implementations for Spring Data repositories

Configuring Fetch- and LoadGraphs

相关问题