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)


arrow_upward
5
arrow_downward

Этот вопрос 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

arrow_upward
5
arrow_downward

ссылка на другой вопрос 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