根据两个不同的约束更新两行

时间:2016-12-02 06:15:55

标签: java mysql hibernate jpql

我有一张表X,其中有一列BALANCE。我有两个行ID和一个值amount。有两个约束变量 - MAX_BALANCEMIN_BALANCE

我需要编写更新查询来更新列BALANCE。第一行ID BALANCE添加了amountamount从第二行ID BALANCE中减去。我需要确保BALANCE始终保持在范围内。也就是说,MIN_BALANCE< = BALANCE< = MAX_BALANCE

如果更新的行数不等于2,我不应该更新一行然后回滚。更新查询应该更新两行(成功案例)或者根本不应该更新任何行。< / p>

我在Java中使用Hibernate,这是我尝试过的查询。它不适用于成功案例。

String sql = "UPDATE X x "
                + "SET x.balance = CASE "
                + "WHEN x.id = :rowId1 THEN (x.balance + :amount) "
                + "WHEN x.id = :rowId2 THEN (x.balance - :amount) "
                + "END "
                + "WHERE x.id IN :ids "
                + "AND ((x.id = :rowId1 AND x.balance + :amount <= :MAX_BALANCE) "
                + "OR (x.id = :rowId2 AND x.balance - :amount >= :MIN_BALANCE))";
        Query query = entityManager.createQuery(sql);

        List<BigInteger> ids = Arrays.asList(new BigInteger(rowId1), new BigInteger(rowId2));


        int rows = query.setParameter("amount", amount)
            .setParameter("ids", ids)
            .setParameter("rowId1", new BigInteger(rowId1))
            .setParameter("rowId2", new BigInteger(rowId2))
            .setParameter("MAX_BALANCE", new Float(MAX_BALANCE))
            .setParameter("MIN_BALANCE", new Float(MIN_BALANCE))
            .executeUpdate();

我不想检查是否rows == 1并抛出异常。更新查询应始终确保行的值为0或2。

或者有没有办法根据Hibernate中的Criteria Update执行此操作?

2 个答案:

答案 0 :(得分:1)

你需要自己加入你的桌子。第一个实例应该有rowid1的记录,第二个实例应该有rowid2的记录。这样,您可以一次性检查两个记录的余额,并决定是否更新。

update x x1 join x x2
set x1.balance=if(x1.balance+:amount <= :MAX_BALANCE,x1.balance+:amount, x1.balance),
    x2.balance=if(x2.balance-:amount >= :MIN_BALANCE,x2.balance-:amount, x2.balance)    
where x1.id=:rowid1 and x2.id=rowid2

答案 1 :(得分:0)

试试这个......

String sql = "UPDATE X x "
+ "SET x.balance = CASE "
+ "WHEN x.id = :rowId1 AND x.balance + :amount <= :MAX_BALANCE THEN (x.balance + :amount) "
+ "WHEN x.id = :rowId2 AND x.balance - :amount >= :MIN_BALANCE THEN (x.balance - :amount) "
+ "END "
+ "WHERE x.id = :rowId1 OR x.id = :rowId2";