2014-11-24 84 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

相關問題