【问题标题】:Duplicate entry for unique key in Database数据库中唯一键的重复条目
【发布时间】:2019-03-29 22:36:14
【问题描述】:

我是 Hibernate 的新手,由于遇到的问题,我放弃了尝试更新/合并 mysql 数据库表中的条目。我对表中的列有一个唯一约束,我想在使用 hibernate 更改数据库中的某些值后对其进行更新,但它永远不会起作用:

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

【问题讨论】:

  • 你试过save吗?
  • 同样的错误java.sql.SQLIntegrityConstraintViolationException: Duplicate entry.. 我没有得到的是,我只想更新字段并将其设置回来.. 但它不允许我。陷入这样的问题真是令人沮丧。我现在失去了将近 2-3 个小时
  • 你能展示一下你是怎么做到的吗?
  • 是的,我已经更新了我的代码。请检查一次

标签: hibernate spring-boot


【解决方案1】:

首先,您必须了解管理实体实例在 Hibernate 中的工作方式。您可以先阅读指南here

在您的示例中,从 weatherToUpdate 实体复制属性后,您需要将 retrievedWeatherData.get(0) 对象作为参数传递给 merge() 函数。

可以手动完成复制,也可以使用 Apache Commons 库中的 BeanUtils.copyProperties() 等辅助实用程序函数完成复制(请参阅 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 Data 来管理休眠实体,或者 Spring boot 对您来说是一个选项。这一点都不难,您不必担心管理数据库事务(启动、提交、回滚),而且您还可以使用一些功能。

【讨论】:

  • 你的方法就像一个魅力。我试过了,现在没有更多错误了。我现在明白了,所以你需要先从数据库中获取数据,然后进行保存,更新操作。
  • 您检索一个休眠托管实体,您可以将其视为数据库中的记录,您可以在其中执行操作。但是,我建议您花一些时间阅读。
  • 好的。是的,我正在阅读并观看视频以了解相同的内容。非常感谢!
猜你喜欢
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 2012-10-16
  • 2014-07-17
  • 1970-01-01
  • 2016-07-14
  • 2017-05-08
  • 1970-01-01
相关资源
最近更新 更多