When does an autogenerated UUID Id get generated with spring data JPA and hibernate? - spring-boot

Suppose you have a class with the following UUID primary key:
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
#Entity
public class MyEntity {
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
// other fields and constructor omitted for brevity
}
When you create a new MyEntity(), the id property is null. That's something I'm used to when the database is responsible for generating the id. In those cases, you must save the entity first before the id is populated. In this case the underlying database is a postgres database with id column type UUID, but the application should be able to generate the Id.
Is there a reason it wouldn't generate automatically and immediately?
Reference: https://thorben-janssen.com/generate-uuids-primary-keys-hibernate/

Related

How to persist object in db with existing primary key in Spring boot JPA?

Scenario:
I do have JSON object as Menus.
//suppose this as
Menus menus = new Menus();
menus.setId(61);
menus.setUrl("test_url");
menus.setName("menu name");
repository.save(menus);
Current case:
It is working fine if db has menu row with id 61 as a result object gets updated.
While row with id=61 does not exists in db then this menu object gets persisted but with new id. ie. a new row is created with new auto generated ID.
Expected:
If menu where id = 61 does not exists in db then menus should be inserted in db with id=61
package com.rasello.auth.entity;
import lombok.*;
import org.hibernate.annotations.Type;
import javax.persistence.*;
#Entity
#Data
#NoArgsConstructor
#Table(name = "menus")
#Getter
#Setter
public class Menus {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
private String name;
private String url;
}
Remove this line #GeneratedValue(strategy = GenerationType.TABLE) and try again. The #GeneratedValue does what the words say. Generates value for the ID and in case you do not need that then you should not use it.
You can read more about how to set up your Ids in this article https://www.baeldung.com/hibernate-identifiers

Unable to insert into table in hibernate

I am trying to create new table and join with ManyToOne relation with my existing table
below is my implementation
New table
#Entity(name="request_city_id")
#Table(uniqueConstraints={#UniqueConstraints{columnNames={"request_id","cityId"})})
#Data
#NoArgsConstructor
#FieldDefault(level=AccessLevel.PRIVATE)
public class RequestCityId{
#GenratedValue(strategy=SEQUENCE, generator="seq_req_city_id")
#SequenceGenerator(name="seq_req_city_id", allocationSize=1)
#Column(name="rc_id")
#Id
long id;
#ManyToOne
#JoinColumn(name="request_id")
Request request;
String cityId;
String status
}
Existing table
#Entity(name="request")
#Data
#NoArgsConstructor
#FieldDefault(level=AccessLevel.PRIVATE)
public class Request{
String frequency
#GenratedValue(strategy=SEQUENCE, generator="seq_req_d")
#SequenceGenerator(name="seq_req_id", allocationSize=1)
#Column(name="request_id")
#Id
long id;
#OneToMany(cascade={ PERSIST, MERGE}, mappedBy="request", fetch=EAGER)
Set<RequestCityId> requestCityIds;
}
but when I am trying to insert into my new table I see my hibernate query gets stuck and just gets timed out after sometime, I am not sure what I am doing wrong here? If I just kep cascade type MERGE then getting
Hibernate Error: a different object with the same identifier value was already associated with the session
First you should create an getters and setters method to each entity.
Request Class
Request City Id Class
this code creates the tables and also saves the data into the table.
Using #Data in entity classes in not recommended because it may cause some problems with jpa as mentioned here.

Spring Boot project: how to set the Entity class if I don't have id as primary key

I am creating a project in spring boot and as an example I am following an exercise on the internet where there is a primary key id and other fields. (the code is below).
When creating Entity / POJO class there is the #Id annotation which indicates that the member field below is the primary key of current entity with the addition of the #GeneratedValue (strategy = GenerationType.IDENTITY) annotation which is used to configure the increment of the specified column (field). And so far everything is clear.
Now a doubt arises; since the exercise I have to do does not have Id as primary key but has a code called PersonCode as primary key composed of both numeric and alphabetic characters (therefore it is not an auto-incremented field, but you have to enter it manually every time you create a new person ), what should be put in place of the #Id and #GeneratedValue annotations?
I hope I have been clear and I apologize for this question, I am a beginner.
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="student")
public class Student {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int student_id;
private String student_name;
private String student_email;
// Get and set methods
}
Since it's a manually generated value, you don't add #GeneratedValue. #Id must be used to indicate that this field represents the primary key.
Naturally, any time a Student is to be saved, it's student_id must be filled in beforehand, Spring won't generate and id for you.

Spring Data + View with Union return duplicate rows

i'm using Spring Boot 2.4.2 and Data module for JPA implementation.
Now, i'm using an Oracle View, mapped by this JPA Entity:
#Entity
#Immutable
#Table(name = "ORDER_EXPORT_V")
#ToString
#Data
#NoArgsConstructor
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class OrderExportView implements Serializable {
private static final long serialVersionUID = -4417678438840201704L;
#Id
#Column(name = "ID", nullable = false)
#EqualsAndHashCode.Include
private Long id;
....
The view uses an UNION which allows me to obtain two different attributes of the same parent entity, so for one same parent entity (A) with this UNION I get the attribute B in row 1 and attribute C in row 2: this means that the rows will be different from each other.
If I run the query with an Oracle client, I get the result set I expect: same parent entity with 2 different rows containing the different attributes.
Now the issue: when I run the query with Spring Data (JPA), I get the wrong result set: two lines but duplicate.
In debug, I check the query that perform Spring Data and it's correct; if I run the same query, the result set is correct, but from Java/Spring Data not. Why??
Thanks for your support!
I got it! I was wrong in the ID field.
The two rows have the same parent id, which is not good for JPA, which instead expects a unique value for each line.
So, now I introduced a UUID field into the view:
sys_guid() AS uuid
and in JPA Entity:
#Id
#Column(name = "UUID", nullable = false)
#EqualsAndHashCode.Include
private UUID uuid;
#Column(name = "ID")
private Long id;
and now everything works fine, as the new field has a unique value for each row.

Hibernate Sequence Conflict after using Audited annotation

I'm using hibernate in my spring boot application
my domain model is like this
#Entity
#Table(name = "skill")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "skill")
#Audited
public class Skill implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
}
The increment size of sequence is 50 and is working properly
but when I add Envers Audited annotation I see this error
conflicting values for 'increment size'. Found [50] and [1]
How can I resolve this conflict?
This doesn't sound like an Envers problem but a general mapping problem.
When you add an #Audited annotation, that simply informs Envers that it should inspect that particular entity mapping during Hibernate bootstrap and create the necessary audit objects to store the entity state during each transaction.
The generated Envers objects use their own sequence generators and primary key. The user defined generation strategy, sequences, etc are all ignored in the Envers object because the associated column is meant to just be a copy/pass-thru value, nothing special.
In other words, the Envers table would have a PK defined that mirrors this POJO:
#Embeddable
public class EnversSkillId implements Serializable {
#Column(name = "REV", nullable = false, updatable = false)
private Integer rev;
#Column(name = "id", nullable = false, updatable = false)
private Long id;
}
When Envers generates the audit record, it automatically uses its internal sequence generator to get the next value and assign it to EnversSkillId#rev and copies your entity's id value directly into the EnversSkillId#id property.
So as mentioned in the comments, your problem is very unlikely related to Envers.

Resources