2016-03-11 2 views
1

Я создаю приложение для загрузки весны с спящим режимом, и у меня есть иерархия DAO. У меня также есть 2 менеджера транзакций для двух разных баз данных.Hibernate использовать диспетчер транзакций для подкласса dao

У меня есть BaseDao, BaseDB1Dao и BaseDB2Dao.

База dao выглядит следующим образом. Я не поддерживаю @Transactional аннотацию с BaseDao.

public interface BaseDao<T extends Serializable> { 

    T create(T t); 

    T read(Class<T> entityClass, long id); 

    void update(T t); 

} 

public abstract class BaseDaoImpl<T extends Serializable> implements BaseDao<T>{ 

    protected abstract Session getSession(); 

    @Override 
    public T create(T t) { 
     getSession().save(t); 
     return null; 
    } 

    @Override 
    @SuppressWarnings("unchecked") 
    public T read(Class<T> entityClass, long id) { 
     return (T) getSession().get(entityClass, id); 
    } 

    @Override 
    public void update(T t) { 
     getSession().update(t); 
    } 
} 

BaseDB1Dao и BaseDB2Dao наследуют и расширить BaseDao с дополнительными функциями, относящимися к схемам в дополнение к основным функциям. Основное отличие состоит в том, что я указываю аннотацию @transactional следующим образом. Я только вывешиваю BaseDB1, потому что они оба почти идентичны

public interface BaseDB1Dao<T extends Serializable> extends BaseDao<T>{ 
    // add additional generic transaction functions here 
} 

@Repository("baseDB1Dao") 
@Transactional("db1TransactionManager") 
public class BaseDB1DaoImpl<T extends Serializable> extends BaseDaoImpl<T> implements BaseDB1Dao<T> { 

    @Autowired 
    @Qualifier("db1SessionFactory") 
    private SessionFactory sessionFactory; 

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

Когда я запускаю приведенный выше код, то чтения запросов работают хорошо и вытащить из соответствующих блоков данных. Но transctional запросы, как создать не работают и не с ошибкой

Could not obtain transaction-synchronized Session for current thread; nested exception is org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread 

Это происходит потому, что один из суб дао BaseDB1Da0, UserDao, просто вызывает основную функцию создания определенного в BaseDao.

Одно решение добавить @Transactional в BaseDaoImpl следующим

@Transactional 
@Repository 
public abstract class BaseDaoImpl<T extends Serializable> implements BaseDao<T>{ 

    protected abstract Session getSession(); 
.... 

Однако это приводит к другой ошибки для как читает и пишет. Это происходит потому, что пользователь создать функцию наследуется от BaseDao, и он идет туда, когда функция создания называется

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: db1TransactionManager,db2TransactionManager 

Так общий вопрос: Есть ли способ использовать tranactionManager класса за ребенком функция в родительском классе

ответ

1

Вам необходимо предоставить выделенный bean-компонент с именем transactionManager, который обрабатывает оба других менеджера транзакций (db1TransactionManager, db2TransactionManager). Spring поддерживает это из коробки просто путем определения пользовательского компонента с именем transactionManager tpye ChainedTransactionManager. Детальная декларация зависит от вашей настройки, поэтому не гарантируется выполнение следующих работ.

@Autowired 
@Bean(name = "transactionManager") 
public PlatformTransactionManager transactionManager(PlatformTransactionManager db1TransactionManager, PlatformTransactionManager db2TransactionManager) 
     throws Exception { 
    return new ChainedTransactionManager(db1TransactionManager, 
      db2TransactionManager); 
} 
+0

Спасибо. Способ, которым мой проект настроен, состоит в том, что у меня есть два отдельных файла конфигурации, имеющие структуру, как показано http://stackoverflow.com/questions/35925768/hibernate-multiple-database-configuration-files. Как бы я назвал эту функцию, поэтому она берет обоих менеджеров транзакций? – Sakib

+0

HibernateTransactionManager - это PlatformTransactionManager, поэтому вы определяете один из них для каждого источника данных и передаете его этому методу. Просто убедитесь, что имя метода у двух других менеджеров транзакций имеет другое имя. (имя метода - имя компонента) –

+0

Спасибо, что сработали. Я просто добавил это в свой основной файл конфигурации базы данных и объединил оба моих файла конфигурации базы данных. – Sakib

Смежные вопросы