我是Hibernate的新手,由于我遇到的问题,我放弃尝试更新/合并mysql数据库表中的条目。我对表中的列有唯一的约束,我想在使用休眠更改数据库中的某些值后对其进行更新,但它永远行不通:
这是我的java类:
package com.weatherapi.test.weather_api.model;
import lombok.Data;
import javax.persistence.*;
@Entity
@Table(name="weather", uniqueConstraints = @UniqueConstraint(columnNames = {"city"}))
@Data
public class Weather {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "city")
private String city;
private String headline;
@Column(name = "descriptions")
private String description;
@Transient
private String wind;
@Transient
private String icon;
private String currentTemp;
private String minTemp;
private String maxTemp;
private String sunrise;
private String sunset;
@Transient
private String unit;
}
,在更改某些值之后,我正在使用session.merge(weatherToUpdate);
将其合并回数据库。但合并失败,甚至saveOrUpdate
也失败。
我的数据库中已经有一个伦敦城市条目,我想从表中提取该条目,合并一些更改并将其上传回数据库。
这是我得到的错误:
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'London' for key 'UK_835v8un5oinaj7vdsvc9ym7ub'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.15.jar:8.0.15]
at
我尝试使用EntityManager通过persist方法解决它,但是我无法在我的设置中安装它。我尝试了不同的方式来更新会话,但没有任何效果。我感到完全迷失了。
编辑:
这就是我要保存的方式:
public void updateCityFromDatabase(Weather weatherToUpdate,String city){
// Create Session
Session session = factory.getCurrentSession();
// Begin Transaction
session.getTransaction().begin();
try{
LOGGER.info("reading the weather data...");
Query query = session.createQuery("from Weather wt where wt.city = :city");
query.setParameter("city",weatherToUpdate.getCity());
List<Weather> retrievedWeatherData = query.list();
if(retrievedWeatherData.get(0).getCity().equals(weatherToUpdate.getCity())){
LOGGER.info("City already exists and parameters are same");
session.save(weatherToUpdate);
}else{
session.clear();
}
session.getTransaction().commit();
LOGGER.info("City parameters Updated!");
factory.close();
}
答案 0 :(得分:1)
首先,您必须了解管理实体实例在Hibernate中的工作方式。您可以先阅读指南here。
在您的示例中,从retrievedWeatherData.get(0)
实体复制属性后,需要将merge()
对象作为参数传递给weatherToUpdate
函数。
可以手动完成复制,也可以使用辅助功能实用程序功能(如BeanUtils.copyProperties())从Apache Commons库进行复制(请参见example)。
因此您的代码变为:
List<Weather> retrievedWeatherData = query.list();
Weather firstRetrievedWeatherData = retrievedWeatherData.get(0);
if (firstRetrievedWeatherData.getCity().equals(weatherToUpdate.getCity())) {
// Manually Copy properties values from weatherToUpdate to retrieved object
// Property value for id is excluded
firstRetrievedWeatherData.setCity(weatherToUpdate.getCity());
firstRetrievedWeatherData.setHeadline(weatherToUpdate.getHeadline());
// Copy more other properties
// Generate an update sql statement instead of insert
session.merge(firstRetrievedWeatherData);
}
最后,如果您选择使用Spring或Spring boot,则建议使用Spring Data来管理休眠实体。这一点都不难,您可以不必担心管理数据库事务(启动,提交,回滚),并且还提供了一些功能。