java - Hibernate merge正在生成新行而不是更新

时间:2015-07-13 08:54:59

标签: java hibernate jpa merge

我正在使用var uuid = $('#fine-uploader').fineUploader('getUuid', id); 。我有多个表使用带有生成值的id。

插入等工作正常,但是当我尝试合并时,Hibernate不会更新旧行并创建新行。

内容相同,但ID正在递增。

合并前: Before merge

合并后: After merge

我尝试使用自定义ID生成器来检查Id是否已存在。有了这个新策略,我得到以下错误:

Hibernate-EntityManager version  4.3.5

修改

我发现@GeneratedValues不会在局部变量中设置id。这意味着您可以在合并时覆盖现有的那些。虽然,这并没有解决我的问题。

以下是我正在使用的代码:

Caused by: java.sql.SQLException: Field 'product_id' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1094)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)

PRODUKT

@Entity(name = "calculation_storage")
@Proxy(lazy = false)
public class CalculationStorage {

@Id
private Date created;

@OneToMany(mappedBy = "storage", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Product> products;

public CalculationStorage(Date created) {
    this.created = created;
    this.products = new LinkedList<Product>() {
        @Override
        public boolean add(Product product) {
            product.setStorage(CalculationStorage.this);
            return super.add(product);
        }
    };
}

public CalculationStorage(Date created, List<Product> products) {
    this.created = created;
    this.products = products;
}

public CalculationStorage() {
}

public Date getCreated() {
    return created;
}

public void setCreated(Date created) {
    this.created = created;
}

/**
 * Durch das aufrufen get add Methode wird der benoetigte Fremdschluesseleintrag gesetzt
 *
 * @return Alle Produkte die registriert sind
 */
public List<Product> getProducts() {
    return products;
}

public void setProducts(List<Product> entities) {
    this.products = entities;
}

发电机:

@Entity(name = "product")
public class Product implements Serializable {

@Id
@Column(name = "product_id")
//@GeneratedValue
@GeneratedValue(strategy=GenerationType.IDENTITY, generator="IdOrGenerated")
@GenericGenerator(name="IdOrGenerated",
        strategy="at.iktopia.firmenverwaltung.abendabrechnung.control.hibernate.ProductIdGenerator"
)
private int id;

private double costs;

private String name;

private ProductType type;

@OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<CalculatorEntity> entities;

@ManyToOne
@JoinColumn(name = "product_fk", nullable = false)
private CalculationStorage storage;

public Product(String name, ProductType type, double costs) {
    this.name = name;
    this.type = type;
    this.costs = costs;
    this.entities = new LinkedList<>();
}

/**
 * JPA - Konstruktor
 */
public Product() {
}

public int getId() {
    return id;
}

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

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public ProductType getType() {
    return type;
}

public void setType(ProductType type) {
    this.type = type;
}

public List<CalculatorEntity> getEntities() {
    return entities;
}

public void setEntities(List<CalculatorEntity> entities) {
    this.entities = entities;
}

public double getCosts() {
    return costs;
}

public void setCosts(double costs) {
    this.costs = costs;
}

public CalculationStorage getStorage() {
    return storage;
}

public void setStorage(CalculationStorage calculationStorage) {
    this.storage = calculationStorage;
}
}

调用以合并对象的更新方法:

public class ProductIdGenerator extends IdentityGenerator {
@Override
public Serializable generate(SessionImplementor session, Object obj) throws HibernateException {
    if (obj == null) throw new HibernateException(new NullPointerException());

    if ((((Product) obj).getId()) == 0) return super.generate(session, obj);

    else return ((Product) obj).getId();
}
}

我无能为力导致这个问题。

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

好吧,我找到了解决方案。非常感谢Kulbhushan Singh让我发现了这个:

我在我的代码中使用@GeneratedValue

@Id
@Column(name = "product_id")
@GeneratedValue
private int id;

我不知道的是,当使用@GeneratedValue时,只有数据库条目才能获得ID。本地对象将具有与以前相同的ID。 (默认为0)。在我的情况下,这意味着数据库中的product_id为1,2,3,......并且在我的对象中它为0。

当我尝试更新我的对象时,我执行了以下操作:

CalculationStorage dbReference = em.getReference(CalculationStorage.class, calculations.getCreated());
dbReference.setProducts(localStorageObject.getProducts());

我基本上将生成的数据库中的ID设置为0,因为我的本地对象中的Id仍为0。

由于我将Id设置为0,数据库生成了新的ID。

编辑:显然,如果重新启动应用程序,本地ID值将再次为0。因此,在需要时尝试从数据库中提取数据,并在完成后让垃圾收集器使用它。