Spring @Transactional объединить и сохранить вопрос

новичок в Spring и здесь @stackoverflow

Я создаю автономное приложение для отслеживания инвентаризации и продаж (Apache Pivot / Spring / JPA / Hibernate / MySQL) для дистрибьюторского бизнеса.

Пока я думаю, что все в CRUD, поэтому я планирую создать базовый класс со всем, что связано с @Transactional.

Затем у меня возникла проблема с моим универсальным методом сохранения. Есть ли разница в методе сохранения и слияния EntityManager из Spring?

Я попытался запустить и вызвал сохранение как для вставки, так и для обновления, и все сработало нормально (я думаю, что Spring автоматически обновляет объект каждый раз, когда я вызываю свой метод сохранения, // видел, что запросы спящего режима регистрируются, это правильно?).

@Transactional
public abstract class GenericDAO {

    protected EntityManager em;

//  em getter+@PersistenceContext/setter

    public void save(T t) {
//        if (t.getId() == null) // create new
//        {
//            em.persist(t);
//        } else // update
//        {
            em.merge(t);
//        }
    }
}

И, кстати, при такой настройке я не сильно скомпрометирую производительность, верно? Как вызов salesDAO.findAll () для создания отчетов (который не обязательно должен быть транзакционным, верно?).

Благодарность!!!


person thirdy    schedule 18.10.2009    source источник


Ответы (2)


Этот вопрос SO является хорошим обсуждением сохранения и слияния, а также принятый ответ очень хорошо это объясняет. Другой ответ также ссылается на хорошее сообщение в блоге об этом.

Согласно первому ответу в этом другом сообщении, похоже, что можно было бы вызвать слияние как для сохранения, так и для обновления объекта, но я сделал это не так. В моих приложениях Spring / JPA я просто использую мои DAO, расширяющие JpaDaoSupport, и использую getJpaTemplate () следующим образом.

/**
 * Save a new Album.
 */
public Album save(Album album) {
    getJpaTemplate().persist(album);
    return album;
}

/**
 * Update an existing Album.
 */
public Album update(Album album) {
    return getJpaTemplate().merge(album);
}
person Kaleb Brasee    schedule 18.10.2009
comment
Я гость, это самый простой способ. Итак, если у меня есть JpaDaoSupport, и я получаю от него объект, любые изменения будут автоматически зафиксированы? Думаю, у меня будет два варианта метода сохранения: один сохраняется, а другой вызывает сброс. Есть какие-нибудь комментарии по этому поводу? - person thirdy; 19.10.2009
comment
Вы имеете в виду автоматическое, как совершенное без сохранения или обновления? Если это так, я бы так не подумал, я всегда просто вызываю сохранение для нового объекта или обновление для существующего, чтобы оно сохранялось. Мне никогда не приходилось вызывать метод flush, но мой доступ к БД довольно прост для любого запроса. - person Kaleb Brasee; 19.10.2009
comment
Мне придется пока отказаться от использования Spring. Просто любопытно, как в Grails это улучшено? Мне не придется сталкиваться с подобными проблемами в Grails, верно? - person thirdy; 19.10.2009

ссылка на другой вопрос SO, опубликованный Калебом, действительно хорошо справляется. покрытия различий и подводных камней persist () vs merge (). Однако я всегда просто реализовывал свои классы Dao с помощью одного метода save (), который вызывает только merge () для обработки как вставок, так и обновлений, и я никогда не сталкивался ни с одним из подводных камней persist () vs merge ().

Что касается производительности и транзакционных методов: использование @Transactional для методов, которые являются только операциями чтения, на самом деле не повлияет на производительность, хотя я предпочитаю использовать аннотации на уровне методов, чтобы я мог легко определить, какие методы являются обновленными, а какие - читаемыми. Вы можете сделать это, установив атрибут readOnly в аннотации @Transactional.

Если вы следуете соглашению об именах в своих методах (т.е. любой метод чтения всегда начинается с getXXX), вы также можете использовать синтаксис указателя в своем конфигурационном файле Spring, чтобы автоматически сделать это различие:

  <tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
      <tx:method name="get*" read-only="true"/>
      <tx:method name="*"/>
    </tx:attributes>
  </tx:advice>

Дополнительную информацию см. В документации Spring по транзакциям.

Кроме того, я обычно помещаю атрибуты @Transactional на один уровень выше моих классов Dao на уровне обслуживания. Тогда методы классов Dao представляют собой отдельные операции с базой данных для каждого вызова метода, тогда как методы службы могут выполнять одну фиксацию / откат для серии обновлений.

person Jason Gritman    schedule 18.10.2009
comment
Спасибо за ответ. Я думаю, что буду придерживаться чистого JPA (мне не нужна гибкость) - person thirdy; 19.10.2009