Unique Key Constraint in Spring Data Jpa - spring-boot

How to make a field unique in pojo using spring data jpa?I know how to do that using jpa
For reference: multi column constraint with jpa
If there is a way, is it possible to use with spring boot?

Use the #UniqueConstraint annotation to specify that a unique constraint is to be included in the generated DDL for a primary or secondary table.
Alternately, to ensure a field value is unique you can write
#Column(unique=true)
String myField;

With Spring Data JPA you are using JPA, so you specify the unique constraint using JPA. Nothing special from Spring Boot or Spring Data on that front.

Um exemplo em Kotlin:
Entity
#Table(name = "TBL_XXX",
uniqueConstraints = [
UniqueConstraint(name = "sessionid_uindex", columnNames = ["sessionId"])
]
)
data class XxxReturn(
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "XXX_ID")
var id: Long? = null,
var sessionId: String,
var msg: String
)

If you have a single column in the table that has UNIQUE KEY constraint then you can simply add the attribute unique=true in the annotation #Column
CODE SNIPPET:
#Column(name = "unique_key_field", nullable = false, unique = true)
String uniqueKeyFied;
In case if you have multiple Unique key constraints in the table then you have to simply follow with the JPA annotations as the spring-boot-data-starter does not provide any special annotations for the table constraints(KEY/UNIQUEKEY).
CODE SNIPPET:
#Entity
#Table(name = "table_name", uniqueConstraints={
#UniqueConstraint( name = "idx_col1_col2", columnNames ={"col1","col2"})
})

Related

Postgresql Spring Data #GeneratedValue without #Id return null value

im working in spring boot project i want to map a property with serial (using my sequence) column in my table and this column is not the ID.
i found this solution :
#Column(name = "DEMANDE_NUMBER", insertable = false, updatable = false, columnDefinition = "serial")
private Integer demandeNumber;
(because #GeneratedValue persist null and doesn't use the sequence)
this solution works fine and the field is persisted in my DB and the value uses the sequence but when i get my object after saving using my repository the demandeNumber is null
Demande savedDemande= demandeRepository.save(demandeToSave);
//demandeObj .getDemandeNumber() return null
any suggestion to resolve this issue please ?
Thanks.
according to this answer How to use a sequence generator for a non ID field?
i added the following annotation on my property
#Generated(GenerationTime.INSERT)
#Column(name = "column_name", columnDefinition = "serial", updatable = false)
you should import the package from hibernate and not javax.persistence.
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
i hope this can help other people in the future. note this solution is for spring data with postgresql.

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.

Race Condition in Postgres SQL using Spring data JpaRepository

I am facing a wierd issue in my implementation where I am persisitng data to a PostgresSQL DB using Spring data JpaRepository
In my Entity class I have the below columns:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private int id;
#Column(name = "field1", nullable = false, length = 16)
private String field1;
#Column(name = "field2", nullable = false, length = 16)
private String field2;
#Column(name = "field3", nullable = false, length = 16)
private String field3;
I initially avoided declaring the fields above as composite since there were many fields to be dealt with as composite keys. I thought the java code check would do the trick in all scenarios
So basically, I have to maintain the uniqueness of each row based on field1,field2 and field3. That was the basic requirement for which I had checks in my java code that if any entry exists in the DB for the combination of field1,field2 and field3 then I used to throw java exceptions
No two rows can have these values repeating. All was good until the application was tested under some errorneous business scenarios which would never happen in production but got run by mistake
Whats happening now is that if 2 requests are triggered at the exact same instance with the exact same 3 fields above (through a script) then they both enter into the Database since both get the entry check as false
Would declaring all of them as one composite key resolve the situation?
You should define the unique constraint in your database in addition of JPA constraint.
#Entity
#Table(uniqueConstraints={
#UniqueConstraint(columnNames = {"field1", "field2", "field3"})
})
public class MyEntity {
...
}

Manage String id sequence in spring boot entity

I'm working on oracle database to manage a JPA entity with a String Primary key.
I cannot modify the type on the PK to a Long or int in the database, so i want to know how to configure the pk sequence in my JPA entity,
i've tried this :
#Id
#SequenceGenerator(name="SEQ_ID", sequenceName = "SEQ_ID" )
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_ID")
#Column(name="SEQ_ID",unique=true, nullable = false,updatable = false)
private String id;
but when persisting a new entity i got the error : Unknown integral data type for ids : java.lang.String
someone can help me please ?
Try removing #GeneratedValue and #SequenceGenerator
Also, a remark, #Id will automatically set unique=true, nullable = false,updatable = false so you can remove them from #Column.
Otherwise, you can check this article for more details about creating a custom string generator https://vladmihalcea.com/how-to-implement-a-custom-string-based-sequence-identifier-generator-with-hibernate/

JPA/Hibernate - Create a table with foreign key only

How can create an entity table using Hibernate that will foreign keys in it a primary key. Consider it to a joining table (with few other attributes) between two tables having many to many relationship between them.
Any sample code?
Any real reason not to use a PK? If the entity has other attributes I would say you are better off with one.
If you really dont want one you can use JPA's #EmbeddedId using a compound key
private UserSessionId id
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "userId", column = #Column(name = "user_id", nullable = false)),
#AttributeOverride(name = "sessionId", column = #Column(name = "session_id", nullable = false)) })
public UserSessionId getId() {
return this.id;
}
public void setId(UserSessionId id) {
this.id = id;
}
Then you can define a separate entity UserSessionId that contains both FK's, at least this is how Hibernate Tools generates compound key relationships
If there are no extra fields involved in the join (ie. foreign keys only). You can use the following technique, no java domain object is required, hibernate will figure it all out for you.
http://www.mkyong.com/hibernate/hibernate-many-to-many-relationship-example-annotation/
You can still have other columns in your table such as creation_date, but their values will need to be updated at the database level.
There are very good examples of composed PK in the JSR document, take a look in JSR 317 in link for persistence-2_0-final-spec.pdf, 2.4 Primary Keys and Entity Identity section have great examples.

Resources