Java Hibernate(4.3.7)PersistentList,不存储修改后的数据
我将实体A和qui A一对多地加载到实体B的列表中。 这将传递给m UI,其中可以添加/删除/修改实体B的列表。 然后,我将在事务处理后在数据库中未设置的实体修改发回。 我想了解为什么以及我必须做些什么才能实现这一目标 (我发现的唯一的后退解决方案是删除所有数据并重新创建;我不认为这是一个卷轴解决方案)。< /P> 以下是我的实体: 实体AJava Hibernate(4.3.7)PersistentList,不存储修改后的数据,java,spring,hibernate,Java,Spring,Hibernate,我将实体A和qui A一对多地加载到实体B的列表中。 这将传递给m UI,其中可以添加/删除/修改实体B的列表。 然后,我将在事务处理后在数据库中未设置的实体修改发回。 我想了解为什么以及我必须做些什么才能实现这一目标 (我发现的唯一的后退解决方案是删除所有数据并重新创建;我不认为这是一个卷轴解决方案)。< /P> 以下是我的实体: 实体A @Entity @Table(name = "GL_RENTAL") public class GlRental implements Serializab
@Entity
@Table(name = "GL_RENTAL")
public class GlRental implements Serializable {
private static final long serialVersionUID = 3721662952504926000L;
@Id
@Column(name = "PK_RENTAL")
@GeneratedValue(generator = "TableGenerator")
@GenericGenerator(name = "TableGenerator", strategy = "com......TableGenerator", parameters = { @Parameter(name = "segment_value", value = "GL_RENTAL") })
private Integer pk;
@Version
@Column(name = "DATE_VERSION")
private Date version;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "PK_UT")
QuantificationRD quantification;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "PK_RENTAL", nullable = false)
@OrderColumn(name = "INDEX_ORDER")
private List<GlRentalPeriod> periods = new ArrayList<>();
...
这是服务
@Service
@Transactional
public class GlUtServiceImpl implements GlUtService {
@Autowired
ProduitService produitService;
@Autowired
ContractService contractService;
@Autowired
UtDao utDao;
@Autowired
GlUtDao glUtDao;
...
@Override
public void updateRental(ContexteService contexte, Integer pkUT, GlRentalBo rentalBo) {
UniteTraitement uniteTraitement = utDao.rechercherUT(pkUT);
QualificationUT qualif = uniteTraitement.getQualification();
Declaration declaration = qualif.getDeclaration();
Gestionnaire gestionnaire = gestionnaireDao.rechercherGestionnaire(contexte.getIdentifiantUtilisateur());
verificationHabilitationService.verifierDroitTraitement(gestionnaire, uniteTraitement);
verificationHabilitationService.verifierOuvertureUT(uniteTraitement);
GlRental rentalDto = rentalBo.getRental();
if (rentalDto.getPk() == null) {
// Attach qualification with rental
UtDao utDao = (UtDao) glUtDao;
QuantificationRD quantif = utDao.rechercherQuantificationRD(pkUT);
if (quantif == null) {
throw new ExceptionPkEntiteInconnu(UT.class, pkUT);
}
if (rentalDto.getQuantification() != null) {
throw new ExceptionConcurrenceOptimiste("Des informations de loyer existent déjà");
}
rentalDto.setQuantification(quantif);
// Save
glUtDao.createRental(rentalDto);
}
else {
GlRental rental = glUtDao.getRental(pkUt)); // error is here, this is readonly request
List<GlRentalPeriod> rentalPeriodRemovals = new ArrayList<>();
for (GlRentalPeriod rentalPeriod : rental.getPeriods()) {
GlRentalPeriod rentalPeriodToRemove = rentalPeriod;
for (GlRentalPeriod rentalPeriodDto : rentalDto.getPeriods()) {
// Period already exists in database : modify date
if (rentalPeriodDto.getPk() != null && Integer.compare(rentalPeriodDto.getPk(), rentalPeriod.getPk()) == 0) {
rentalPeriodToRemove = null;
rentalPeriod.setAmount(rentalPeriodDto.getAmount());
rentalPeriod.setDateStart(rentalPeriodDto.getDateStart());
rentalPeriod.setDateEnd(rentalPeriodDto.getDateEnd());
rentalPeriod.setFranchise(rentalPeriodDto.getFranchise());
rentalPeriod.setFranchiseType(rentalPeriodDto.getFranchiseType());
rentalPeriod.setFranchiseUnit(rentalPeriodDto.getFranchiseUnit());
rentalPeriod.setPaid(rentalPeriodDto.getPaid());
rentalPeriod.setType(rentalPeriodDto.getType());
break;
}
}
// Period not found, to remove, set it in a list of periods to remove from database
if (rentalPeriodToRemove != null) {
rentalPeriodRemovals.add(rentalPeriod);
}
}
if (CollectionUtils.isNotEmpty(rentalPeriodRemovals)) {
rental.getPeriods().removeAll(rentalPeriodRemovals);
}
// Additionnal periods
List<GlRentalPeriod> rentalPeriodAdditionnals = rentalDto.getPeriods().stream().filter(period -> period.getPk() == null)
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(rentalPeriodAdditionnals)) {
rental.getPeriods().addAll(rentalPeriodAdditionnals);
}
glUtDao.updateRental(rental);
}
}
}
@服务
@交易的
公共类GlUtServiceImpl实现GlUtService{
@自动连线
ProduitService ProduitService;
@自动连线
合同服务合同服务;
@自动连线
宇道宇道;
@自动连线
GlUtDao GlUtDao;
...
@凌驾
public void updateRental(ContexteService contexte、整数pkUT、GlRentalBo rentalBo){
unitetraitment unitetraitment=utDao.rechercherUT(pkUT);
QualificationUT qualification=uniteTraitment.getQualification();
声明=qualif.getDeclaration();
Gestionnaire Gestionnaire=gestionnaireDao.rechercherGestionnaire(contexte.getIdentificationUsilizateur());
verificationHabilitationService.VerifierDroittRaiment(gestionnaire,UnitTraitement);
verificationHabilitationService.VerifierOutertureUT(UniteTraitment);
GlRental rentalDto=rentalBo.getRental();
if(rentalDto.getPk()==null){
//将资格与租金挂钩
UtDao UtDao=(UtDao)glUtDao;
QuantificationRD quantif=utDao.rechercherQuantificationRD(pkUT);
如果(quantif==null){
抛出新的ExceptionPKENTITENNU(UT.class,pkUT);
}
if(rentalDto.getQuantification()!=null){
抛出新的例外情况ConcurrenceOptimate(“Des informations de loyer existing déjá”);
}
rentalDto.setQuantification(quantif);
//拯救
createRental(rentalDto);
}
否则{
glrent rent=glUtDao.getrent(pkUt));//此处有错误,这是只读请求
List rentalPeriodRemovals=新建ArrayList();
for(GlRentalPeriod rentalPeriod:rent.getPeriods()){
GlRentalPeriod rentalPeriod TOREMOVE=rentalPeriod;
对于(GlRentalPeriod rentalPeriodTo:rentalTo.getPeriods()){
//数据库中已存在期间:修改日期
if(rentalPeriodDto.getPk()!=null和&Integer.compare(rentalPeriodDto.getPk(),rentalPeriod.getPk())==0){
rentalPeriodToRemove=null;
setAmount(rentalPeriodTo.getAmount());
rentalPeriod.setDateStart(RentalPeriodTo.getDateStart());
rentalPeriod.setDateEnd(rentalPeriodTo.getDateEnd());
rentalPeriod.set特许经营权(rentalPeriodDto.get特许经营权());
rentalPeriod.Set特许经营类型(RentalPeriodTo.Get特许经营类型());
rentalPeriod.set特许经营单位(rentalPeriodDto.get特许经营单位());
rentalPeriod.setPaid(rentalPeriodDto.getPaid());
setType(rentalPeriodTo.getType());
打破
}
}
//找不到句点,若要删除,请在要从数据库中删除的句点列表中设置它
如果(rentalPeriodToRemove!=null){
添加(rentalPeriod);
}
}
if(收款提成不为空(租金期间移动)){
rental.getPeriods().removeAll(rentalPeriodRemovals);
}
//附加期
List RentalPeriodAdditionals=rentalDto.getPeriods().stream().filter(period->period.getPk()==null)
.collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(RentalPeriodAdditionals)){
rental.getPeriods().addAll(rentalperiodadditionals);
}
glUtDao.updateRental(租赁);
}
}
}
解释我的pb帮助我解决了问题。
Pb是简单的。
为我服务,我打电话
GlRental rental = glUtDao.getRental(pkUt));
这是一个只读方法
@Override
public GlRental getRental(Integer pkUt) {
Session session = sf.getCurrentSession();
Query query = session.createQuery("select rental from com.galian.claims.core.model.GlRental rental where rental.quantification.pk = :pkUt");
query.setInteger("pkUt", pkUt);
// to avoid saving any modification when transaction is closed
//The Caller can perform modification but they must no be saved
query.setReadOnly(true);
GlRental rental = (GlRental) query.uniqueResult();
return rental;
}
(我很糟糕)若数据检索为只读,则不会设置对实体的任何修改。
所以我就这么做,用这个方法
public GlRental getRentalByPk(Integer pkRental) {
return (GlRental) sf.getCurrentSession().get(GlRental.class, pkRental);
}
所以现在我只是想知道是否最好发布DTO数据、加载实体、删除、更新、修改其数据,或者直接发布实体并“合并”它,而不必在持久化实体中传递和复制DTO。而不查看实际持久化实体的代码,可能使用EntityManager,我们看不出你做错了什么。我可能会用服务代码更新我的副本。多亏了你的问题,我找到了问题所在。它是如此的愚蠢,我没有看到它。在更新案例中,当my object Rental的PK不为空时,我加载此对象以修改中的数据列表。但是我忘记了名为returnreadonly data的方法。所以我用另一种方法修复了它,它直接通过对象的PK检索数据
public GlRental getRentalByPk(Integer pkRental) {
return (GlRental) sf.getCurrentSession().get(GlRental.class, pkRental);
}