Reputation: 821
I am new to Hibernate and gave up trying to update/merge an entry in the mysql database table because of the problem i've ran into. I have a unique constraint on a column in the table and I want to update it after changing some values in the database using hibernate but it never works:
This is my java class:
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;
}
and I am using session.merge(weatherToUpdate);
to merge it back to the database after changing some values. but merge fails and even saveOrUpdate
fails.
My database already has a city London entry into it which i want to extract from the table, merge some changes and upload it back to database.
Here is the error that i get:
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
I tried using EntityManager to solve it using persist method, but i simply cannot install it in my setup. I tried different ways to update session but nothing works. i feel completely lost.
EDIT:
This is how i am trying to save:
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();
}
Upvotes: 0
Views: 1891
Reputation: 2910
First of all, you have to understand the way managing entity instances work in Hibernate. You can start by reading a guide here.
In your example, you need to pass retrievedWeatherData.get(0)
object as an argument to merge()
function after you copy the properties from weatherToUpdate
entity.
Copy can be done either manually or using a helper utility function as BeanUtils.copyProperties() from Apache Commons library (see an example).
So your code becomes:
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);
}
Finally, I would recommend the usage of Spring Data for managing hibernate entities, if using Spring, or Spring boot is an option for you. It is not difficult at all, you can stop worrying about managing DB transactions (start, commit, rollback) and also you are provided with a handful set of features.
Upvotes: 1