HibernateDaoSupport, транзакция не откатывается - PullRequest
5 голосов
/ 27 января 2011

Я играю с Spring + Hibernate и некоторым «ручным» управлением транзакциями с PostgreSQL. Я хотел бы попробовать это и понять, как это работает, прежде чем переходить на управление транзакциями на основе AOP.

@Repository
public class UserDAOImpl extends HibernateDaoSupport implements UserDAO {

    @Override
    public void saveUser(User u) {
        Transaction tx = getSession().beginTransaction();
        getHibernateTemplate().saveOrUpdate(u);
        tx.rollback();

    }
}

Вызывая saveUser здесь, я бы предположил, что сохранение нового пользователя будет отменено.Однако, переходя к командной строке psql, пользователь сохраняется в таблице.

Почему это не отменено, что я должен настроить для выполнения транзакций таким образом?

Редактировать;кажется, что немного больше отладки указывает на то, что getHibernateTemplate () использует сеанс, отличный от того, что getSession () возвращает (?)

Изменение кода на

Transaction tx = getSession().beginTransaction();
getSession().persist(u);
tx.rollback();

, и транзакция откатывается.Но я до сих пор не понимаю, почему hibernateTemplate будет использовать / создавать новый сеанс ..

Ответы [ 2 ]

2 голосов
/ 27 января 2011

Если вы видите JavaDoc для HibernateDaoSupport.getSession (), он говорит, что получит новый сеанс или даст вам тот, который используется существующей транзакцией. В вашем случае транзакция с HibernateDaoSupport не указана.

Так что если вы используете getHibernateTemplate (). GetSession () вместо просто getSession (), вы должны получить сеанс, который используется HibernateTemplate, и тогда вышеприведенное должно работать.

Пожалуйста, дайте мне знать, как это происходит.

EDIT:

Я согласен, это защищено ... мой плохой. Таким образом, другой вариант заключается в том, чтобы сохранить привязку потока сеанса, что обычно является наилучшей практикой в ​​веб-приложении. Если HibernateDaoSupport собирается найти сессию, связанную с потоком, то он не будет создавать новый и использовать тот же. Это должно позволить вам сделать откаты.

2 голосов
/ 27 января 2011

На ум приходит пара возможностей (без каламбура):

a) Ваш драйвер JDBC по умолчанию имеет значение autocommit = true и каким-то образом игнорирует вызовы beginTransaction () и rollback ();

b) Если вы используете Spring 3, я считаю , что SessionFactory.getSession () возвращает объект Hibernate Session, заключенный в прокси Spring. Прокси-сервер Spring настроен на Session частично для управления транзакциями, и, возможно, возможно, что он мешает вашим ручным вызовам транзакций?

Хотя вы, безусловно, можете использовать прокси в области AOP для управления транзакциями, почему бы не использовать аннотацию @Transactional (readOnly = false | true) в ваших методах уровня обслуживания? В вашем конфигурационном файле Spring для методов уровня обслуживания все, что вам нужно сделать, чтобы сделать эту работу, это добавить

<tx:annotation-driven />

См. Главы 10 и 13 справочной документации Spring по управлению транзакциями и доступу к данным ORM соответственно:

http://static.springsource.org/spring/docs/3.0.x/reference/index.html

Наконец, если вы используете Spring 3, вы можете исключить ссылки на Spring Framework в своем коде, вставив bean-компонент SessionFactory в Spring-прокси в ваш код DAO - больше нет необходимости использовать HibernateDaoSupport. Просто введите SessionFactory, получите текущий сеанс и используйте Hibernate в соответствии с примерами Hibernate. (При необходимости вы можете комбинировать как HibernateDaoSupport, так и простой код Hibernate на основе SessionFactory в одном приложении.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...