2015-04-01 1 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()); 
} 

И если это необходимо, мой метод для преобразования 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: Data has changed. updated [0] rows sql

Что я сделал не так?

ответ

0

Я вижу некоторые проблемы здесь:

  1. Вы используете два поля Version. Я не знаю, хорошо ли это для Ebean, но обычно этого достаточно. Также я думаю, что Ebean самостоятельно будет управлять этими полями, поэтому вам может быть лучше указать поле версии, которое вы не хотите использовать (int, чтобы служить счетчиком или временной меткой последнего изменения);
  2. Вы звоните update но, кажется, вы действительно создаете новую транзакцию, так что вы должны использовать Ebean.save

Что касается ошибок, то исключение при попытке обновить запись, которая изменилась между время загрузки и обновление. Чтобы узнать, что запись изменилась, Ebean использует значения из столбцов Version.

Так обновление в коде будет генерировать SQL, похожее на это:

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

который бы не обновлять какие-либо записи и выбросить это исключение.

Я размещаю эту информацию, потому что я не знаю, как легко отключить оптимистичную блокировку в версии Ebean, которая поставляется с Play < 2.4.x, и вы, вероятно, найдете эту ошибку снова. В общем случае вы можете свести его к минимуму с помощью поля версии и использовать транзакции или перезагрузить/повторить операцию.

+0

Это нормально, если я положил '@ Version' в поле Id? – Mornor

+0

№ Добавить новый столбец с именем version, и вы можете его забыть – Salem

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 –

0

У меня есть альтернативное решение этой проблемы вы можете использовать:

@EntityConcurrencyMode(ConcurrencyMode.NONE) 

в вашем Entity класса

Это отключит Оптимистическая блокировка параллельной проверки модификации новый запрос SQL будет:

update TABLE-NAME SET PARAM1 =? ГДЕ ID =?

EntityConcurrencyMode поставляется в пакете
package com.avaje.ebean.annotation;