联合主键

近期找一个数据不一致的问题,花了一周时间找bug,感觉很经典。虽然是填离职同事留下的坑。由于插入了很多错误数据,还需要一周的时间去手动修改错误数据(1千多条错误数据)。很坑啊有木有!!

他的代码是这样的:

@Entity
public class PaymentDetailVO implements Serializable {
    @Id
    public Long duesdetailid;

    public String paymenttype;
    @Id
    public String paymethod;

    public BigDecimal payamount;

    
}
// 前面代码省略

    paymentdetailsql.append("select t.id as duesdetailid,")
                                        .append("  '1' as paymenttype,")
                                        .append(" ddl.value as paymethod,")
                                        .append(" (sum(ts.price)-nvl(sum(tr.returnamount),0)-nvl(sum(tc.ticketprice),0)) as  payamount")
                                        .append(" from Ticketturnoverdetail t ")
                                        .append(" left join ticketsell ts on t.id = ts.turnoverdetailid ")
                                        .append(" left join ticketreturn tr on t.id=tr.turnoverdetailid ")
                                        .append(" left join ticketcancel tc on t.id=tc.turnoverdetailid ")
                                        .append(" left join digitaldictionarydetail ddl on ddl.digitaldictionaryid=50 and ddl.code=ts.paymethod")
                                        .append("  where (ts.paymethod <> '0' and ts.paymethod <> '2' and ts.paymethod <> '3')   and t.id=:id")
                                        .append(" group by ddl.value,'1',t.id")
                                        .append(" union all")
                                        .append(" select t.id as duesdetailid,")
                                        .append("  '1' as paymenttype,")
                                        .append(" ddl.value as paymethod,")
                                        .append(" (sum(ts.price)-nvl(sum(tr.returnamount),0)-nvl(sum(tc.ticketprice),0)) as  payamount")
                                        .append(" from Ticketturnoverdetail t ")
                                        .append(" left join ticketsellagent ts on t.id = ts.turnoverdetailid ")
                                        .append(" left join ticketreturn tr on t.id=tr.turnoverdetailid ")
                                        .append(" left join ticketcancel tc on t.id=tc.turnoverdetailid ")
                                        .append(" left join digitaldictionarydetail ddl on ddl.digitaldictionaryid=50 and ddl.code=ts.paymethod")
                                        .append("  where (ts.paymethod <> '0' and ts.paymethod <> '2' and ts.paymethod <> '3')   and t.id=:id")
                                        .append(" group by ddl.value,'1',t.id");
                        Query ticketquery = JPA.em().createNativeQuery(paymentdetailsql.toString(),PaymentDetailVO.class);
                        ticketquery.setParameter("id", ticketturnoverdetail.getId());
                        List<PaymentDetailVO> paymentdetaillist = new ArrayList<PaymentDetailVO>();
                        try {
                            paymentdetaillist = ticketquery.getResultList();
                        } catch (Exception e) {
                            e.printStackTrace();
                            play.Logger.error("=============:%s", e.getMessage());
                        }
                        for(PaymentDetailVO paymentdetail : paymentdetaillist){
                            PaymentDetail _paymentdetail = new PaymentDetail();
                            _paymentdetail.duesdetailid=paymentdetail.duesdetailid;
                            _paymentdetail.paymenttype=paymentdetail.paymenttype;
                            _paymentdetail.paymethod=paymentdetail.paymethod;
                            _paymentdetail.payamount=paymentdetail.payamount;
                            _paymentdetail.createtime=new Date();
                            _paymentdetail.save();
                        }

//后面代码省略

看出问题了么?他使用

duesdetailid和paymethod作为联合主键,但是查询语句用的是union all 将2个group by 给连接起来。插入paymentdetail 的时候jpa认为是第一条和第二条是同一条数据,导致第一条数据插入了2次,而第二条没有插入。

如何修改呢?只要把外面再套一层group by 就行了。然后paymenttype也要加入联合主键。前面加上@Id


原文地址:https://www.cnblogs.com/feiyunaima/p/6758418.html