2015-04-01 70 views
2

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

Transaction.javaOptimisticLockException Ebean即使使用@Version

@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()); 
} 

而且如果有必要,我的方法来转换一个StringTimestamp

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: Data has changed. updated [0] rows sql

我做错了什么?

回答

0

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

  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> 

这将不更新任何记录,并抛出该异常。

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

+0

如果我把'@ Version'放在Id字段上,可以吗? – Mornor 2015-04-03 12:01:55

+0

否。添加一个名为version的新列,您可以忘记它是否 – Salem 2015-04-03 13:56:21

4

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

1) Use @EntityConcurrencyMode(ConcurrencyMode.NONE) before class name

2) Use raw update query.(preferred)

我面临着因为同样的ebean.update抛出乐观锁定异常的太多问题,最后我做到原料更新查询,它为我工作。

+0

@EntityConcurrencyMode不再用于最新版本“ebean 8.2.3”(它与sbt-play-ebean版本3.1.0一起使用 – 2016-10-13 15:00:40

0

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

@EntityConcurrencyMode(ConcurrencyMode.NONE) 

在实体类

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

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

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