数据库中唯一键的重复条目

时间:2019-03-29 22:36:15

标签: hibernate spring-boot

我是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();
}

1 个答案:

答案 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来管理休眠实体。这一点都不难,您可以不必担心管理数据库事务(启动,提交,回滚),并且还提供了一些功能。