EBean没有做更新! 它试图执行插入和失败(EBean is not doing update

2019-09-20 09:04发布

我有一个简单的用户模型是这样的:

package models;

import java.util.*;
import javax.persistence.*;
import play.db.ebean.*;

@Entity
public class User extends Model {

        @Id
    public Long id;
    public String userName;
    public String email;
    public String workPlace;
    public Date birthDate;
    @Version
    public Long version;

    public static Finder<Long,User> find = new Finder<Long,User>(
        Long.class, User.class
    );

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getWorkPlace() {
        return workPlace;
    }

    public void setWorkPlace(String workPlace) {
        this.workPlace = workPlace;
    }

    public Date getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }
}

在MySQL已经存在一个具有ID = 1,版本= 1的纪录

我创建一个具有相同的id +版本的新模式,更改用户名

然后我尝试save()方法

它失败:

javax.persistence.PersistenceException: ERROR executing DML bindLog[] error[Duplicate entry '1' for key 'PRIMARY']
        at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:116) ~[ebean.jar:na]
        at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.java:76) ~[ebean.jar:na]
        at com.avaje.ebeaninternal.server.persist.DefaultPersistExecute.executeInsertBean(DefaultPersistExecute.java:91) ~[ebean.jar:na]
        at com.avaje.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:527) ~[ebean.jar:na]
        at com.avaje.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:557) ~[ebean.jar:na]
        at com.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:404) ~[ebean.jar:na]
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [na:1.7.0_05]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) [na:1.7.0_05]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) [na:1.7.0_05]
        at java.lang.reflect.Constructor.newInstance(Unknown Source) [na:1.7.0_05]
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) ~[mysql-connector-java-5.1.18.jar:na]
        at com.mysql.jdbc.Util.getInstance(Util.java:386) ~[mysql-connector-java-5.1.18.jar:na]

我究竟做错了什么? 插入新记录的作品。 所以它看起来对我来说,在那里它没有认识到它应该做一个更新一些ebean错误。 或者是它的一些配置,我忘了什么地方?

谢谢

Answer 1:

我认为这是相关的字节码增强,无论播放和ebean执行。

我不得不与你类似的奇怪问题,当我混有getter和setter的公共领域。 有时直接使用现场时,值未设置:

user.id = 1L;   // didn't work
user.setId(1L); // ok

这感觉就像一个潜在的死亡陷阱,所以我决定是一致的,只有使用公共领域。 其缺点是,ebeans自动提取停止工作,但另一方面,迫使我调整我的查询与ebean取。

这个优秀的帖子由蒂莫揭示ebean和发挥如何执行他们的字节码魔的一些情况。



Answer 2:

如果你有一个自我创造的对象,并调用保存(),然后Ebean使得insert语句作为SQL。 如果你调用update(),它会进行更新语句作为SQL。

有一个在Ebean本身没有逻辑,这将使到数据库的额外查询只是为了检查,如果刚好有与数据库类似主键列,如果是用其他方式的更新语句的INSERT语句。 这将仅仅是它的一部分效率低下的行为,因为通常你会知道哪一个进行,因此不想执行两个SQL语句,只有一个。 在这种情况下,你确实有告诉它使用的更新,不要尝试再次插入行。

// Create user.
User user1 = new User();
user1.setId(1L);
user1.setVersion(1L);
user1.setUserName("foo");
user1.setWorkPlace("bar");
user1.setEmail("foo@bar.com");
user1.save();

// Change details later and update DB.
User user2 = new User();
user2.setId(1L);
user2.setVersion(1L);
user2.setUserName("scooby_doo");
user2.save(); // This will crash.
user2.update(); // This will work.

但是,如果从数据库获取对象,然后调用save()就可以将在SQL中使用的更新语句,因为Ebean知道它的状态是不是新的,而不是现有的。

// Find user (and let Ebean know its state as an existing row).
User user3 = User.find.byId(1L);

// Now you can change details and save without issues.
user3.setEmail("foo@gmail.com");
user3.setVersion(2L);
user3.save(); // This will work.

见Ebean文档 。



文章来源: EBean is not doing updates! it's trying to do inserts and failing