java-Hibernate合并正在生成新行,而不是更新
我使用的是Hibernate EntityManager版本4.3.5。我有多个使用id和生成值的表 插入之类的操作很好,但是当我尝试合并Hibernate时,它不会更新旧的行并创建新的行 内容相同,但id正在增加 合并前: 合并后: 我尝试使用自定义Id生成器检查Id是否已经存在。使用此新策略,我得到以下错误:java-Hibernate合并正在生成新行,而不是更新,java,hibernate,jpa,merge,Java,Hibernate,Jpa,Merge,我使用的是Hibernate EntityManager版本4.3.5。我有多个使用id和生成值的表 插入之类的操作很好,但是当我尝试合并Hibernate时,它不会更新旧的行并创建新的行 内容相同,但id正在增加 合并前: 合并后: 我尝试使用自定义Id生成器检查Id是否已经存在。使用此新策略,我得到以下错误: Caused by: java.sql.SQLException: Field 'product_id' doesn't have a default value at com.m
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)
编辑:
我发现@GeneratedValues不会在局部变量中设置ID。这意味着您可以在合并时覆盖现有的。不过,这并没有解决我的问题
以下是我正在使用的代码:
@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;
}
为合并对象而调用的更新方法:
public class CalculationManager implements Manager<CalculationStorage, Date, CalculationStorageList> {
/**
* @see Manager#save(Object)
*/
@Override
public void save(CalculationStorage calculationStorage) {
Validate.notNull(calculationStorage);
EntityManager em = PersistenceManager.getInstance().getEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try {
em.persist(calculationStorage);
transaction.commit();
} catch (Exception e) {
ErrorHandler.handleException(e, JPA_PERSIST_ERROR_MESSAGE);
if (transaction.isActive())
transaction.rollback();
}
em.close();
}
/**
* @see Manager#update(Object)
*/
@Override
public void update(CalculationStorage calculations) {
Validate.notNull(calculations);
EntityManager em = PersistenceManager.getInstance().getEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try {
CalculationStorage c = em.getReference(CalculationStorage.class, calculations.getCreated());
c.setProducts(calculations.getProducts());
em.merge(c);
transaction.commit();
} catch (EntityNotFoundException e) {
if (transaction.isActive())
transaction.rollback();
save(calculations);
} catch (Exception e) {
ErrorHandler.handleException(e, JPA_PERSIST_ERROR_MESSAGE);
if (transaction.isActive())
transaction.rollback();
}
em.close();
}
/**
* @see Manager#getAll()
*/
@Override
public CalculationStorageList getAll() {
EntityManager em = PersistenceManager.getInstance().getEntityManager();
List<CalculationStorage> calculations;
try {
calculations = em.createQuery("SELECT c FROM calculation_storage c").getResultList();
} catch (Exception e) {
ErrorHandler.handleException(e, JPA_LOAD_ERROR_MESSAGE);
return null;
}
em.close();
return new CalculationStorageList(calculations);
}
/**
* @see Manager#remove(Object)
*/
@Override
public void remove(Date primaryKey) {
Validate.notNull(primaryKey);
EntityManager em = PersistenceManager.getInstance().getEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try {
em.remove(em.getReference(CalculationStorage.class, primaryKey));
transaction.commit();
} catch (Exception e) {
ErrorHandler.handleException(e, JPA_PERSIST_ERROR_MESSAGE);
if (transaction.isActive())
transaction.rollback();
}
em.close();
}
/**
* @see Manager#get(Object)
*/
@Override
public CalculationStorage get(Date primaryKey) {
Validate.notNull(primaryKey);
EntityManager em = PersistenceManager.getInstance().getEntityManager();
try {
CalculationStorage storage = em.getReference(CalculationStorage.class, primaryKey);
em.close();
return storage;
} catch (Exception e) {
ErrorHandler.handleException(e, JPA_LOAD_ERROR_MESSAGE);
return null;
}
}
}
我不知道是什么导致了这个问题。好吧,我找到了解决办法。非常感谢库尔布尚·辛格,他让我了解了这一点: 我在代码中使用@GeneratedValue:
@Id
@Column(name = "product_id")
@GeneratedValue
private int id;
我不知道的是,当使用@GeneratedValue时,只有数据库条目获得ID。本地对象将具有与以前相同的ID。默认情况下为0。在我的例子中,这意味着数据库中的产品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。因此,当您需要数据时,尝试从数据库中提取数据,并在完成后让垃圾收集器接收数据。您不需要任何自定义生成器使合并按文档所述工作。使用标准生成器,发布您的实体和再现问题的测试用例,以便我们了解您做错了什么。@JBNizet我添加了相关代码。@Ajan这不正是发生的吗?对象的ID将被返回,它是一个整数。如果我从数据库中设置了ID,那么新行不会被插入?是否使用以前的ID更新现有行\
@Id
@Column(name = "product_id")
@GeneratedValue
private int id;
CalculationStorage dbReference = em.getReference(CalculationStorage.class, calculations.getCreated());
dbReference.setProducts(localStorageObject.getProducts());