我想問一下這種行爲的推理,因爲看起來我並不完全理解運行到Spring的和merge()
在Spring中的區別@Transactional
方法/類。當@Transactional方法拋出一個異常時,Hibernate merge()的行爲
我有這應該回滾DB操作,但它不會(全班被註釋爲@Transactional
)下面的代碼:
@Override
public MyBean assignNewFoo(Integer id, Integer idNewFoo) {
MyBean bean = myBeanRepository.findOne(id);
bean = myBeanRepository.save(bean);
bean.setNewFoo(
fooManagement.findById(idNewFoo)
);
if (true) throw new RuntimeException();
return bean;
}
下面的代碼不會回滾按預期的例外是拋出:
@Override
public MyBean assignNewFoo(Integer id, Integer idNewFoo) {
MyBean bean = myBeanRepository.findOne(id);
myBeanRepository.save(bean);
bean.setNewFoo(
fooManagement.findById(idNewFoo)
);
if (true) throw new RuntimeException();
return bean;
}
的保存()方法來自類org.springframework.data.jpa.repository.support.SimpleJpaRepository
,所以它的代碼是:
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
該實體是一個現有的實體,所以我明白它正在做一個merge()
。按照JPA specification:
find方法(只要它會被調用在鎖定或與 LockModeType.NONE調用)並且是 在事務上下文中調用不需要的getReference方法。 如果有 事務範圍的持久化上下文的實體管理器在使用時,所產生的 實體將被分離;如果使用具有擴展 持久性上下文的實體管理器,則會對其進行管理。
合併操作允許狀態從分離 實體傳播到由實體管理器管理的持久性實體。是應用到實體X合併操作的 語義 如下:
- 如果X是一個分離的實體,X的狀態被複制到預先存在的管理實體實例的相同的X」身份或X的新管理副本X'被創建。
- 如果X是新實體實例,則創建新的託管實體實例X',並將X的狀態複製到實例X'中的新託管實體中。
- 如果X是一個除去實體實例,一個IllegalArgumentException將由合併操作拋出(或事務提交將 失敗)。
- 如果X是一個被管實體,它將被合併操作忽略,但是,合併操作被級聯到由X關聯的實體 如果這些關係已被註釋爲 級聯元素值cascade = MERGE或級聯=所有註釋。
- 用於Y通過從X具有級聯元件值級聯關係中引用的所有實體= MERGE或級聯= ALL,Y合併 遞歸爲Y」。對於由X引用的所有這樣的Y,X'被設置爲 引用Y'。 (請注意,如果管理X,則X與 X'是同一個對象。)
- 如果X是與X'合併的實體,並且引用了另一個實體Y,其中cascade = MERGE或cascade = ALL未指定,則從X'導航同一關聯產生對 的引用管理對象Y」具有相同持久化標識爲Y.
如果
merge(
返回副本)的假想管理實體,爲什麼存儲在數據庫中的變化,當我使用分離的一個? (除非有例外,這是我想要的行爲)爲什麼無論如何改變提交,如果我修改新的託管實體但拋出異常?
編輯按照要求通過@艾倫乾草:
package org.customer.somefoos.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.customer.somefoos.entity.MyBean;
import org.customer.somefoos.repository.MyBeanRepository;
import org.customer.somefoos.service.MyBeanManagement;
import org.customer.somefoos.service.FooManagement;
@Service
@Transactional
public class MyBeanManagementImpl implements MyBeanManagement {
@Resource
private MyBeanRepository myBeanRepository;
@Resource
private FooManagement fooManagement;
@Override
public List<MyBean> findAll() {
return myBeanRepository.findAll();
}
@Override
public MyBean findById(Integer id) {
return myBeanRepository.findOne(id);
}
@Override
public void delete(Integer id) {
myBeanRepository.delete(id);
}
@Override
public MyBean save(MyBean myBean) {
return myBeanRepository.save(myBean);
}
@Override
public MyBean assignNewFoo(Integer id, Integer idNewFoo) {
MyBean bean = myBeanRepository.findOne(id);
myBeanRepository.save(bean);
bean.setNewFoo(
fooManagement.findById(idNewFoo)
);
if (true) throw new RuntimeException();
return bean;
}
}
你可以發佈整個類的代碼嗎? –
完成。你認爲別的地方有什麼問題嗎,@AlanHay? – jplatasv