前段时间做项目遇到了一个问题,这里总结一下
环境
需要添加合同主表信息与从表信息(从表中需要存储主表id),因为bean在另一个项目中,但是却公用数据库,所以我们不能使用jpa
的save(对象)
方法。只能写sql
,然后调用对应的createNativeQuery
的方法。问题出现了。。。
因为是在service
中处理,service
的一个方法因为事务的原因将整个方法都走完才commit
坑爹的来了 。。。我先添加主表信息,然后再倒序查询主表,获取id
赋值给从表,但是无论如何我获取的都是上一个主表记录的id
但是控制台已经显示执行了主表插入的sql
….就是因为事务的原因 他并没有commit
所以也没有id
解决办法
1.首先我尝试将主从添加写到两个service中,但是因为项目逻辑的原因 他们都需要在另外一个serivice中调用,所以还是在一个事务里面没有提交
2.我后来想到了flush
和 refresh
同步缓存和数据库 ,让他强制提交,最终呢还是不行
3.(真正的解决办法)
最终我才用JdbcTemplate
问题轻松解决
List<TContact2> contracts = this.supplierInfoWebServiceDao.search2(TContact2.class,"select * from contactbuy where id = "+id);
if(null==contracts){
throw new BusinessException("获取合同信息出错");
}
if(contracts.size()>0){
final TContact2 contract = contracts.get(0);
KeyHolder keyHolder = new GeneratedKeyHolder();
dao.getJdbcTemplate().update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
StringBuffer sbMain = new StringBuffer("");
sbMain.append("INSERT INTO mxinterface_purchasecontract ");
sbMain.append("(contactcode,contractName,contractTotalMoney,projectDepartmentCode,projectDepartmentName,returnMessage,returnTime,success,supplcode,supplname) ");
sbMain.append("values(?,?,?,?,?,?,?,?,?,?)");
PreparedStatement ps = con.prepareStatement(sbMain.toString(), Statement.RETURN_GENERATED_KEYS);
ps.setString(1, contract.getContactcode());
ps.setString(2, contract.getContractName());
ps.setString(3, contract.getContractTotalMoney());
ps.setString(4, contract.getProjectInterfaceCode());
ps.setString(5, contract.getPurchaseDeptName());
ps.setString(6, "");
// ps.setString(7, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
ps.setString(7, null);
ps.setString(8, "0");
ps.setString(9, contract.getSupplcode());
ps.setString(10, contract.getSupplname());
return ps;
}
}, keyHolder);
// 主表ID
final int approveID = Integer.valueOf(keyHolder.getKeyList().get(0).get("GENERATED_KEY").toString());
List<TContactDetail2> contractDetails = this.supplierInfoWebServiceDao.search2(TContactDetail2.class,"select * from contactbuydetail where contactid = "+id);
if(null!=contractDetails&&contractDetails.size()>0){
for(TContactDetail2 detail:contractDetails){
String sql = "INSERT INTO mxInterface_purchaseContractDetail VALUES(NULL,"+approveID+","
+ "'"+detail.getContactwzcode()+"','"+detail.getContactwzdetail()+"','"+detail.getContactwzmodel()+"','"+detail.getContactwzname()+"',"
+ ""+detail.getContactwznum()+",'"+detail.getContactwzunit()+"',"+detail.getContractMoney()+","+detail.getContractPrice()+")";
dao.getJdbcTemplate().update(sql);
}
}
}
这个方法可以直接返回新添加的主表Id
,类似于 jpa
的save(对象)
方法 也会直接commit
当然这个方法可以直接返回Id
,另外我发现直接用JdbcTemplate
的实例对象update
也会提交事务,只是Id
需要我们再查一次而已
最后采用3方法,我估计JdbcTemplate
和 jpa
可能底层实现不一样吧
具体的实现原理和其中的原因还希望大家指出
另外如果有更好的方法也请指教 ~~~