【问题标题】:OptimisticLockException Ebean even with @VersionOptimisticLockException Ebean 即使使用@Version
【发布时间】:2015-04-01 14:11:42
【问题描述】:

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

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

我做错了什么?

【问题讨论】:

    标签: java orm playframework timestamp ebean


    【解决方案1】:

    有几种方法可以处理这个问题。

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

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

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

    【讨论】:

    • @EntityConcurrencyMode 在最新版本“ebean 8.2.3”中不再使用(与 sbt-play-ebean 版本 3.1.0 一起使用
    【解决方案2】:

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

    1. 您正在使用两个版本字段。我不知道这对 Ebean 是否合适,但通常一个就足够了。此外,我认为 Ebean 将自行管理这些字段,因此您最好指定一个您不想使用的版本字段(一个 int 作为计数器或上次更改的时间戳);
    2. 您正在调用update,但您似乎真的在创建一个新事务,所以您应该使用Ebean.save

    关于错误,当您尝试更新在加载和更新之间发生更改的记录时,会引发该异常。为了找出记录已更改,Ebean 使用版本列中的值。

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

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

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

    我发布此信息是因为我不知道在 Play

    【讨论】:

    • 我把@Version放在Id字段上可以吗?
    • 没有。添加一个名为 version 的新列,您可以忘记它在那里
    【解决方案3】:

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

    @EntityConcurrencyMode(ConcurrencyMode.NONE)
    

    在你的实体类中

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

    更新 TABLE-NAME SET PARAM1=?哪里 ID = ?

    EntityConcurrencyMode 包含在包中
    包 com.avaje.ebean.annotation;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-28
      • 2013-08-13
      相关资源
      最近更新 更多