Remove Duplicate entry '59' for key 'PRIMARY in Hibernate - mysql

I am very new in Hibernate. I am using Hibernate with JPA. I have an annotated entity class and a table related to that entity class.
#Entity
public class Test implements Serializable {
#Id
#GenericGenerator(name="inc" , strategy="identity")
#GeneratedValue(generator="inc")
private int id;
private String address; // setter getter and constructor
}
When saving this entity, it insert the data into the db. But during application running process another application is inserting data into same table. when my application try to save the data then Duplicate entry '59' for key 'PRIMARY' exception generated. So I want to use a generator which can insert the data and generate id in database level rather than application level and the identifier must saved back to my entity.

Use the Table generator strategy or the sequence generator.

You do not have to specify a generator. You can use the default generator and never set the id manually. If the error still comes post your merge/persist method.
More informations about generators can you found here https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing
#Entity
public class Test implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String address; // setter getter and constructor
}

Related

Reading data using Spring data jpa automatically converting timestamp to current timezone

I have a table User with columns
user_id, first_name,last_name, created_time(timestamp)
I have a class User Entity
#Getter
#Setter
#Table(name="user")
#Entity
public class User {
#Id
private Long userId;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="created_time")
private Timestamp createdTime;
}
I have an interface User Repository
public interface UserRepository extends CRUDRepository<User,Long> {
User findByUserId(Long id);
}
The created_time stored in database table is 2020-09-08 15:38:13 and when i read the object using spring data jpa it returned as "2020-09-08 21:08:13"
How should i ensure that this automatic time zone conversion not to happen?
The root cause of the problem is that Jackson automatically converts the timestamp values to UTC and then serializes the same.
In order to correct this behavior, you can add following property to your application.properties and specify the same timezone value as is being used by your DB server.
spring.jackson.time-zone=Asia/Kolkata
There is an article that explains this problem and also proposes solutions.
You can also have a look at this answer.

How can I make hibernate not override ID in object to be saved, and rather use its ID?

I'm trying to save a Foo object with ID=20. In my MySQL db the last row has Foo with ID=5. When I use the save function in the JpaRepository, it saves the object, but instead of using the ID I wanted it to have (20), it uses 6.
#Entity
#Data
#ToString
#NoArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class Foo implements Serializable {
#Id
private long id;
I have tried with #GeneratedValue(strategy = GenerationType.IDENTITY), but that doesn't work either. Is there a way to configure Hibernate not take the next sequential ID, but use what is stored in the object?

JacksonMapping Exception :: HttpMessageNotWritableException: Could not write content: (was java.lang.NullPointerException)

Framework Spring MVC 4.x
Hibernate 4.x
Jackson 2.8
I have two columns one is publishDate and createdDate. Publish date user need to manually enter it. Created date in MySQL column has a default set as CURRENT_TIMESTAMP, so when an entry is created DB will automatically timestamp the entry.
I have a book POJO publishDate and createdDate field... publishDate can handle null data for some reason. But Timestamp field gets an exception. Why is this?
org.springframework.http.converter.HttpMessageNotWritableException: Could not
write content: (was java.lang.NullPointerException) (through reference chain:
java.util.HashMap["results"]->java.util.ArrayList[30]-
>com.app.books.Book["dateCreated"]); nested exception is
com.fasterxml.jackson.databind.JsonMappingException: (was
java.lang.NullPointerException) (through reference chain:
java.util.HashMap["results"]->java.util.ArrayList[30]-
>com.app.books.Book["dateCreated"])
I tried to suppress this by adding annotation, I tried several of them because I keep reading conflicting info on the comments section on which to use.
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) // but show JsonSerialize is deprecated
#JsonInclude(Include.NON_NULL)// Include can not be resolved as variable
#JsonInclude(JsonInclude.Include.NON_DEFAULT) // finally doesn't give me an error but I still get the same exception.
This is my book Class
#Entity
#Table(name="books")
#Component
public class Book implements Serializable{
/**
*
*/
private static final long serialVersionUID = -2042607611480064259L;
#Id
#GeneratedValue
private int id;
#NotBlank
private String name;
#NotBlank
#Size(min=2, max=16)
private String ispn;
#DecimalMin(value = "0.1")
private double price;
//#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
//#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
//#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_DEFAULT)
private Timestamp dateCreated;
private Date datePublished;
Very wried... Thanks for helping..
You may have better results switching from primitives (int & double) to Java classes (Int & Double) in your Book class. See JsonMappingException (was java.lang.NullPointerException) also JSON: JsonMappingException while try to deserialize object with null values

Persisting a Many-to-Many entity by adding to a List of entities

I am getting a list of entities and attempting to add more values to it and have them persist to the data base... I am running into some issues doing this... Here is what I have so far...
Provider prov = emf.find(Provider.class, new Long(ID));
This entity has a many to many relationship that I am trying to add to
List<Organization> orgList = new ArrayList<Organization>();
...
orgList = prov.getOrganizationList();
So I now have the list of entities associated with that entity.
I search for some entities to add and I place them in the orgList...
List<Organization> updatedListofOrgss = emf.createNamedQuery("getOrganizationByOrganizationIds").setParameter("organizationIds", AddThese).getResultList();
List<Organization> deleteListOfOrgs = emf.createNamedQuery("getOrganizationByOrganizationIds").setParameter("organizationIds", DeleteThese).getResultList();
orgList.addAll(updatedListofOrgss);
orgList.removeAll(deleteListOfOrgs);
As you can see I also have a list of delete nodes to remove.
I heard somewhere that you don't need to call persist on such an opperation and that JPA will persist automatically. Well, it doesn't seem to work that way. Can you persist this way, or will I have to go throught the link table entity, and add these values that way?
public class Provider implements Serializable {
#Id
#Column(name="RESOURCE_ID")
private long resourceId;
...
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name="DIST_LIST_PERMISSION",
joinColumns=#JoinColumn(name="RESOURCE_ID"),
inverseJoinColumns=#JoinColumn(name="ORGANIZATION_ID"))
private List<Organization> organizationList;
...//getters and setters.
}
The link table that links together organizations and providers...
public class DistListPermission implements Serializable {
#Id
#Column(name="DIST_LIST_PERMISSION_ID")
private long distListPermissionId;
#Column(name="ORGANIZATION_ID")
private BigDecimal organizationId;
#Column(name="RESOURCE_ID")
private Long resourceId;
}
The problem is that you are missing a cascade specification on your #ManyToMany annotation. The default cascade type for #ManyToMany is no cascade types, so any changes to the collection are not persisted. You will also need to add an #ElementDependent annotation to ensure that any objects removed from the collection will be deleted from the database. So, you can change your Provider implementation as follows:
#ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
#ElementDependent
#JoinTable(name="DIST_LIST_PERMISSION",
joinColumns=#JoinColumn(name="RESOURCE_ID"),
inverseJoinColumns=#JoinColumn(name="ORGANIZATION_ID"))
private List<Organization> organizationList;
Since your Provider class is managed, you should not need to merge the entity; the changes should take effect automatically when the transaction is committed.

Can not set java.lang.Integer field id to org.hibernate.id.IdentifierGeneratorHelper

I need to store some data in a MySQL-database using Jpa 2/Hibernate 3.5.1. For legacy reasons the table I want to store data in has a compound primary key. The first part of the primary key is of type INTEGER (auto-increment-value), the second part is of type BIGINT (Long in Java-code - to be set manually before persisting).
I have implemented (example code below the stacktrace) the combined primary key via the #IdClass-Annotation, the first-key-part also has a generation strategy set: #GeneratedValue(strategy = GenerationType.IDENTITY)
When trying to persist an object with code like this
...
TestData testData = new TestData("data");
testData.setIdPartTwo(2L);
entityManager.getTransaction().begin();
entityManager.persist(testData);
entityManager.getTransaction().commit();
the following exception is thrown:
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of org.example.persistence.TestDataId.idPartOne
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1174)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:674)
at org.example.persistence.PersistenceTest.shouldPersistTestData(PersistenceTest.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:640)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:627)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:799)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1103)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:137)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:121)
at org.testng.TestRunner.runWorkers(TestRunner.java:1098)
at org.testng.TestRunner.privateRun(TestRunner.java:727)
at org.testng.TestRunner.run(TestRunner.java:581)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:315)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:310)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:272)
at org.testng.SuiteRunner.run(SuiteRunner.java:221)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:40)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:83)
at org.testng.internal.thread.ThreadUtil$CountDownLatchedRunnable.run(ThreadUtil.java:151)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of org.example.persistence.TestDataId.idPartOne
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:151)
at org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:438)
at org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:122)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:800)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:774)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:778)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:668)
... 24 more
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Integer field org.example.persistence.TestDataId.idPartOne to org.hibernate.id.IdentifierGeneratorHelper$2
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
at java.lang.reflect.Field.set(Field.java:657)
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:139)
... 35 more
My entity-class looks like this:
#Entity
#IdClass(TestDataId.class)
public class TestData implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idPartOne;
#Id
private Long idPartTwo;
private String data;
public TestData() {}
// getters and setters
// hashCode() and equals()
}
The combined-primary-key:
public class TestDataId implements Serializable {
private static final long serialVersionUID = 1L;
private Integer idPartOne;
private Long idPartTwo;
public TestDataId() {}
// getters and setters
// hashCode() and equals()
}
Test-Table was created with the following statement:
CREATE TABLE `testdb`.`testdata`
(`idPartOne` INTEGER NOT NULL AUTO_INCREMENT,
`idPartTwo` BIGINT(20) NOT NULL DEFAULT 0,
`data` VARCHAR(45),
PRIMARY KEY(`idPartOne`, `idPartTwo`))
ENGINE = InnoDB;
Changing the GenerationType to TABLE would make it work, but would generate idPartOne-values in steps of ~32.000. Unfortunately, another application uses this very same database-table without JPA/Hibernate and is nicely incrementing this id-part in steps of 1.
It is required that the id-generation is done in the same way no matter which application stores data into this table (that is, id incrementing of 1). What would be the best solution to achieve this? Hint, we cannot change the other application!
Any help is really appreciated.
Thx,
Markus
Does it work when you annotate the embedded id?
#Embeddable
public class TestDataId
{
#GeneratedValue(strategy = GenerationType.TABLE)
private Integer idPartOne;
private Long idPartTwo;
}
#Entity
public class TestData
{
#EmbeddedId
private TestDataId key;
private String data;
}