OptimisticLockException Ebean甚至包含@Version

时间:2015-04-01 14:11:42

标签: java orm playframework timestamp ebean

我尝试使用Ebean程序中的Play! Framework更新数据库中的一行。
这是我想要更新的实体的类。

Transaction.java

@Entity
@Table(name = "transactions")
public class Transaction extends Model{

    @Id
    @GeneratedValue
    public int id; 
    @OneToOne
    @JoinColumn(name = "car_fk")
    public Car car; 
    @OneToOne
    @JoinColumn(name = "user_lender_fk")
    public User user; 
    @Version
    public Timestamp from_date; 
    @Version                    
    public Timestamp to_date;  
    public boolean availability; // true -> Available. 
    public String status; 
}

以下是我用来更新它的方法:

Transaction transaction = new Transaction(); 
transaction.car = concernedCars.get(i); 
transaction.user = currentUser; 
transaction.from_date = Tools.StringAndroidToTimestamp(dateFrom); 
transaction.to_date = Tools.StringAndroidToTimestamp(dateTo); 
transaction.status = Constants.WAITING_FOR_ANSWER; 
try{
    Ebean.update(transaction); 
}catch(OptimisticLockException e){
    Logger.info(e.toString());
}

如有必要,我的方法是将 String转换为Timestamp

public static Timestamp StringAndroidToTimestamp(String s){
        String toConvert = s.substring(0, s.length()-2); 
        Logger.info("ToConvert = "+toConvert);
        Timestamp timestamp = null; 
        try{
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parsedDate = dateFormat.parse(toConvert);
            timestamp = new Timestamp(parsedDate.getTime());
        }catch(Exception e){
            Logger.info("Exception date = " +e.toString());
        }
        return timestamp;
    }

当然,我收到了一个神话般的错误:

  

javax.persistence.OptimisticLockException:数据已更改。更新   [0]行sql

我做错了什么?

3 个答案:

答案 0 :(得分:4)

有几种方法可以解决这个问题。

  

1)在类名之前使用@EntityConcurrencyMode(ConcurrencyMode.NONE)

     

2)使用原始更新查询。(首选)

我面临太多问题,因为同样的ebean.update抛出乐观锁异常,最后我做了原始更新查询,它对我有用。

答案 1 :(得分:0)

我可以从这里看到一些问题:

  1. 您正在使用两个版本字段。我不知道这对Ebean是否正常,但通常一个就足够了。另外我认为Ebean会自行管理这些字段,因此最好指定一个你不想使用的版本字段(一个int用作计数器或最后一次更改的时间戳);
  2. 您正在呼叫update但似乎您确实在创建新的交易,因此您应该使用Ebean.save
  3. 关于错误,当您尝试更新在加载它和更新之间发生更改的记录时,会引发该异常。为了找出记录已更改,Ebean使用Version列中的值。

    因此,代码中的更新将生成类似于此的SQL:

    UPDATE transactions
    SET car_fk=<SOME_VAL>, ... 
    WHERE id=null AND from_date=<OTHER_VAL> AND to_date=<ANOTHER_VAL>
    

    不会更新任何记录并抛出该异常。

    我发布此信息是因为我不知道在Play&lt; 2.4.x附带的Ebean版本中禁用乐观锁定的简单方法,您可能会再次发现该错误。通常,您可以使用版本字段并使用事务或重新加载/重试操作来最小化它。

答案 2 :(得分:0)

我有一个解决这个问题的替代方案 你可以使用:

@EntityConcurrencyMode(ConcurrencyMode.NONE)

在您的实体类

这将禁用乐观锁定并发修改检查 新的SQL查询将是:

更新TABLE-NAME SET PARAM1 =? WHERE ID =?

EntityConcurrencyMode来自包
package com.avaje.ebean.annotation;