2013-02-15 32 views
1

我一直在毆打我的頭撞牆一段時間,現在試圖讓這個工作。我創建了以下數據訪問對象:休眠事務處理管理器 - Java配置

public interface GenericDAO<T, ID extends Serializable> { 
    T findById(ID id); 
    List<T> findAll(); 
    T save(T entity); 
    void update(T entity); 
    void delete(T entity); 
} 

public class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> { 

    private final Class<T> persistentClass; 
    private final SessionFactory sessionFactory; 

    public GenericHibernateDAO(final SessionFactory sessionFactory) { 
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    this.sessionFactory = sessionFactory; 
    } 

    protected Session getSession() { 
    return sessionFactory.getCurrentSession(); 
    } 

    public Class<T> getPersistentClass() { 
    return persistentClass; 
    } 

    @Override 
    public T findById(final ID id) { 
    return (T) getSession().load(getPersistentClass(), id); 
    } 

    @Override @SuppressWarnings("unchecked") 
    public List<T> findAll() { 
    return findByCriteria(); 
    } 

    protected List<T> findByCriteria(final Criterion... criterion) { 
    final Criteria crit = getSession().createCriteria(getPersistentClass()); 
    for (final Criterion c : criterion) { 
     crit.add(c); 
    } 
    return crit.list(); 
    } 

    @Override 
    public T save(final T entity) { 
    getSession().saveOrUpdate(entity); 
    return entity; 
    } 

    @Override 
    public void delete(final T entity) { 
    getSession().delete(entity); 
    } 

    @Override 
    public void update(final T entity) { 
    getSession().saveOrUpdate(entity); 
    } 
} 

@Repository 
public class StockHibernateDAO extends GenericHibernateDAO<Stock, String> implements StockDAO { 

    @Inject 
    public StockHibernateDAO(final SessionFactory sessionFactory) { 
    super(sessionFactory); 
    } 
} 

我試圖用Java的配置設置的,所以這裏是我的配置設置我的服務層:

@Configuration @Profile("hibernate") 
@EnableCaching @EnableTransactionManagement 
@ComponentScan("reference.dao.hibernate") 
public class HibernateServiceConfig implements TransactionManagementConfigurer { 

    @Inject private StockDAO stockDao; //No extra methods, just the base stuff for now 

    @Bean(destroyMethod = "shutdown") 
    public DataSource dataSource() { 
    return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("classpath:schema.sql").build(); 
    } 

    @Bean 
    public SessionFactory sessionFactory() { 
    return new LocalSessionFactoryBuilder(dataSource()).addAnnotatedClasses(Stock.class) 
    .setProperty("hibernate.show_sql", "true") 
    .setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory") 
    .setProperty("hibernate.cache.use_query_cache", "true") 
    .setProperty("hibernate.cache.use_second_level_cache", "true") 
    .setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect").buildSessionFactory(); 
    } 

    @Override @Bean 
    public PlatformTransactionManager annotationDrivenTransactionManager() { 
    return new HibernateTransactionManager(sessionFactory()); 
    } 

} 

這裏是TradingService :

@Service 
public class TradingServiceImpl implements TradingService {  
    @Inject private StockDAO stockDAO; 

    @Override @Transactional 
    @CachePut(value = "stockCache", key = "#stock.name") 
    public Stock addNewStock(final Stock stock) { 
    stockDAO.save(stock); 
    return stock; 
    } 

    @Override @Cacheable(value = "stockCache") 
    public Stock getStock(final String stockName) { 
    return stockDAO.findById(stockName); 
    } 

    @Override @CacheEvict(value = "stockCache", key = "#stock.name") 
    public void removeStock(final Stock stock) { 
    stockDAO.delete(stock); 
    } 

    @Override @CacheEvict(value = "stockCache", key = "#stock.name") 
    public void updateStock(final Stock stock) { 
    stockDAO.update(stock); 
    } 

    @Override 
    public List<Stock> getAll() { 
    return stockDAO.findAll(); 
    } 
} 

只有在保存方法中添加了session.flush()才能完成股票的保存。我理解事物的方式是,使用TransactionManager和@Transactional圍繞服務層方法實際上應該爲我創建該調用。缺少這個配置是什麼?

+0

刪除@Inject StockDao並使用'@ Repository'註釋該類或其實現。 – 2013-02-15 20:01:36

回答

3

因爲你注入Session

@Bean 
    public Session session() { 
    return sessionFactory().openSession(); 
    } 

春天不能增加它的周圍事務的行爲。讓春天打開會議,並做它的業務。

代替注入Session,注入SessionFactory。在您的DAO中,保留SessionFactory的屬性並使用sessionFactory.getCurrentSession()來獲取會話。

當Spring看到@Transactional時,它會得到SessionFactory,呼叫openSession(),在它上面開始一個事務,然後調用你的方法。當您的方法成功返回時,它將關閉該事務。

您應該也可能在您服務班的@Autowired道。

+0

如果我的DAO被劃分爲@Transactional(即不是隻有在事務中才有意義的getCurrentSession()纔有效)?現在,我想用事務標記服務層,而不是我的DAO層。 – Scott 2013-02-15 19:43:47

+0

無論誰擁有@Transactional,默認情況下,方法調用中的任何內容都將使用相同的會話和事務。 – 2013-02-15 19:44:45

+0

然後,仍然不太正確,因爲我收到以下堆棧:org.hibernate.HibernateException:未找到當前線程的會話 at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) 在org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:978) at reference.dao.hibernate.GenericHibernateDAO.getSession(GenericHibernateDAO.java:25) – Scott 2013-02-15 19:47:28