Persist hibernate entity with pk generated by trigger - oracle

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.

Related

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.

JPA query after save doesn't return database generated field

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

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/

#Id annotation Causing duplication in list

I am using Hibernate for calling Stored procedure
Response returned by Stored procedure
receiverId fcmId source
1234 xyz android
45678 abc web
9876 fgh android
1234 ygh ios
Hibernet #EntityClass
#Entity
public class receieverDetails {
#Id
#Column(name="receiverId")
private String receiverUserId;
#Column(name="fcmId")
private String fcmIds;
private String source;
}
I am getting List of receiverDetails from database
if List contain duplicate receiverId as show is above response, 1st one is replacing the 4th details
Code for Binding
ProcedureCall procedureCall1 =
session.createStoredProcedureCall(Strings.StoredProcedureNames.GET_RECEIVER_INFO_OF_SPONSORED_MESSAGE,receieverDetails.class);
Output output1 = procedureCall1.getOutputs().getCurrent();
if(output1.isResultSet()) {
List<receieverDetails> receievers = ((ResultSetOutput) output1).getResultList();
}
i think this is causing by #Id annotation in the entity class, Because it is happening with same receiverIds only
Kindly Help me on this
In your code by providing the #Id annotation to the column receiverId, you are telling the code that this field is to be used as the primary key for the table.So, when fetching the data the issue occurs as there are duplicate values in the table for this column. Either you need to set the primary key correctly, or make this column as primary key in table and correct your code.
If you are using the same entity class to persist data and make column receiverId primary key then try using the below :
#Entity
public class receieverDetails {
#Id
#Column(name="receiverId",unique=true,nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private String receiverUserId;
#Column(name="fcmId")
private String fcmIds;
private String source;
}
unique=true in #Column is a shortcut for #UniqueConstraint(columnNames = {"receiverId"} and other particular constraints.The #GeneratedValue annotation is to configure the way of increment of the specified column(field).
or if the primary key of the table is some other field in table please correct the code to reflect the same.

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.

Resources