Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: thirdyОтветов: 2

новичок в 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 () для создания отчетов (который не обязательно должен быть транзакционным, верно?).

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

javaspringjpa

Ответы

Ответ 1 · рейтинг 5 · Kaleb Brasee

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

Ответ 2 · рейтинг 5 · Jason Gritman

ссылка на другой вопрос 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 представляют собой отдельные операции с базой данных для каждого вызова метода, тогда как методы службы могут выполнять одну фиксацию / откат для серии обновлений.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы