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