JPA query after save doesn't return database generated field - spring

I'm trying to save this model to a database, and then retrieve what I just saved. Every field is retrieved except for the database generated UUID field.
#Entity
#Table(name = "usertoken")
public class UserToken implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "token", insertable = false, updatable = false, nullable = false)
private UUID token;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="usersid", nullable=false)
private User user;
#Column(name = "expiration", updatable = false, nullable = false)
private LocalDateTime expiration;
I save the token from within the service
token = tokenRepository.save(token);
which generates this SQL
Hibernate:
insert
into
usertoken
(expiration, usersid)
values
(?, ?)
The next statement gets the token
token = tokenRepository.findByUser(user);
I see the SQL select includes the token field
Hibernate:
select
usertoken0_.id as id1_8_,
usertoken0_.expiration as expirati2_8_,
usertoken0_.token as token3_8_,
usertoken0_.usersid as usersid4_8_
from
usertoken usertoken0_
where
usertoken0_.usersid=?
...but the returned object has every field populated BUT the token. The database does have a value in the token column.
I'm at a loss as to why it would populate every field but one.
Here's the table in question:
CREATE TABLE public.usertoken
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
usersid integer NOT NULL,
token uuid NOT NULL DEFAULT uuid_generate_v1(),
expiration timestamp without time zone NOT NULL,
CONSTRAINT "usertoken_pkey" PRIMARY KEY (id)
)
I forgot to add that when I query later on the token is found and the UUID field is properly populated. So something weird with JPA caching? Are database DEFAULT column values ignored by hibernate after the insert?
tokenRepository.findByToken(UUID.fromString(userToken));
Hibernate:
select
usertoken0_.id as id1_8_,
usertoken0_.expiration as expirati2_8_,
usertoken0_.token as token3_8_,
usertoken0_.usersid as usersid4_8_
from
usertoken usertoken0_
where
usertoken0_.token=?

You have to signal hibernate that field is being generated by database. So add the following:
#org.hibernate.annotations.Generated(value = GenerationTime.INSERT)
#Column(name = "token", insertable = false,
updatable = false, nullable = false)
private UUID token;
You will also see hibernate issues a select just for that column after insert

Related

Get list of database errors on saveAll()

I have a CountryObject:
#Entity
#Table(name = "country")
class CountryObject(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
val id: Long? = null,
#Column(name = "name")
val name: String,
#Column(name = "ISO2", length = 2)
val ISO2: String,
#Column(name = "ISO3", length = 3)
val ISO3: String
) : Serializable
with the corresponding PostgreSQL create script that has some unique constraints on ISO2 and ISO3:
CREATE TABLE country
(
id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
iso2 VARCHAR(2) NOT NULL,
iso3 VARCHAR(3) NOT NULL,
CONSTRAINT pk_country PRIMARY KEY (id)
);
ALTER TABLE country
ADD CONSTRAINT UNIQUE_CONSTRAINT_ISO2 UNIQUE (iso2);
ALTER TABLE country
ADD CONSTRAINT UNIQUE_CONSTRAINT_ISO3 UNIQUE (iso3);
Along with this I have a corresponding repository:
#Repository
interface CountryRepository : JpaRepository<CountryObject, Long>
And out of the box implementation of the CountryRepository has a saveAll() method that tries to insert a list of objects into the country table. So far, everything behaves as expected.
Once I try to insert a list that have multiple objects violating the unique constraints, the exception is thrown on the first and stopped. What I want to have is to get some list with the errors that I can use as a report, which mentions which entries failed saving. Of course nothing should be saved in that case and the transaction is rolled back.
Any hints how something like this can me achieved? Of course one option would be to try to save each object separately and then collect the errors, but that might be not that performant.

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/

oracle with spring boot not fetching by primary key

I have written a spring boot app with oracle db.
Below is my entiry class.
#Entity
public class SystemTypeLookup{
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
#Type(type = "uuid-char")
#Column(name = "ID", updatable = false, nullable = false)
protected UUID id;
#Column(name = "CODE")
private String code;
}
And in passing my own UUID as primary key value.
In oracle db ID is considered as RAW and the UUID stored in oracle is differently.
There is no - separation in oracle and all the UUID chars are in upper case.
When i try to find the entity using primary key it is not fetching the row with id. I'm always getting null.
#Resource(name = "coreRepository")
private ErpEntityRepository coreRepositoryBase;
SystemTypeLookup systemTypeLookup = coreRepositoryBase.findOne("WHERE o.id='"+id+"'", SystemTypeLookup.class);
when is pass 76c03cd9-3d96-40c5-8df9-aad8f2369453 as id value then the oracle will insert the id without '-' and all chars will be in upper case.
So how to solve this issue?
First of all you should use parameters in your query and second make sure that the id you are passing is of type UUID and not String.

Persist hibernate entity with pk generated by trigger

I have Oracle database.
In my table i have trigger, which fire up when some row is inserted. That works fine, when i use it from SQLDeveloper. But in Java I want to insert some row using Hibernate 3.3. Te body of my trigger is not really important, let's say it defines id of the row upon current time.
My POJO entity looks like:
#Entity
#Table( name = "user" )
public class User implements Serializable
{
private static final long serialVersionUID = 1;
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY )
#Column( nullable = true, length = 14, name = "user_id" )
private Long userId;
#Column( nullable = true, length = 80, name = "name" )
private String name;
//getters and setters
}
Here is my code for persisting new user:
SessionFactory sessionFactory = sessionFactoryManager.getCurrentSession();
Session session = sessionFactory.openSession();
User user = new User();
user.setName("TEST");
session.persist(user);
session.flush();
As you can see I don't set the userId field because it should be set by my trigger before inserting a row, but it doesn't work. I found, that trigger will be called if I add #GeneratedValue annotation, but it seems it doesn't work on Oracle database: I have an error:
Dialect does not support identity key generation
Trying to resolve this error I only found articles about using sequence, but I don't want to use sequence, I have to use trigger.

Resources