How to create custom id generator for primary key in springboot
very clear question in title
132 Replies
⌛
This post has been reserved for your question.
Hey @userexit! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./close
or theClose Post
button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
Stack Overflow
How to generate Custom Id in JPA
i want generate Custom Id in JPA it must be primary key of table.
there are many examples to create Custom Id using hibernate like this
i want same implementation but in JPA.The id must be alphanu...
very clear answer on Stack Overflow ;)
though you might also check the second answer with some updated code
Also I would use
try
-with-resources for closing JPA things@dan1st genericgenerator is deprecated
Ah right, there's
IdGeneratorType
https://docs.jboss.org/hibernate/orm/6.6/javadocs/org/hibernate/annotations/IdGeneratorType.html
You can create your own annotation and annotate it with
IdGeneratorType
so thats the way now ?
make my own annotation
yes
see the Javadoc here
it has examples for pretty much exactly that use case there
public CustomSequenceGenerator(CustomSequence config, Member annotatedMember,
CustomIdGeneratorCreationContext context)
kinda dumb to pass teh CustomIdGeneratorCreationContext
since we pass the hibernate session in the generate method
I think that gives you information on what entity it is about or something like that
I cant seem to find the doc for it
I know the first config contains the info passed in our custom annotation
and that annotatedMember has info about the attribute or method
but that last one idk
maybe you can use it to get information on the entity
not just the field name
also these custom annotations
are they only good for
generation of id
or can they be used for other stuff
also for other things
You can do all sorts of custom stuff with it
Also just because it's passed, it doesn't mean you have to use it
it gives good enough information
about the database
the mapping of the entity
etc
context.getDatabase().getPersistentClass()
good use case i can see for this
is making a generator that uses prefix and subfix
for example
and since u can choose both of them through the annotation
it can be general
or literally anything else ;)
so u think its fien to get nextval from sequence with this:
Please close the objects that should be closed
doesnt garbage collector do that ?
I edited the second answer to that question to show how
The GC collects unused memory. But some things (marked
Closeable
/AutoCloseable
should be closed by you
this is if it has to do some extra logic when it isn't used any more
for example telling the DB "I don't need that any more"/disconnecting from the DBokay well I guess closing stmt and con then
maybe add a finally clause
You can do it with a try-with-resources statement
which is what's done in the second answer
try-with-resources ?
what happened to try-catch-finally
😭
ive seen that many times
i thought it was just different syntax
lol
that's roughly equivalent to
meaning it makes sure the closing is handled correctly
and if you have multiple acquired resources in a
try
block, it closes all of them properly
There are a few pitfalls when using try
-finally
for closing resources and try
-with-resources makes it easy to do that correctlyso the try (resource)
will close other resources inside the try
that are not listed between parenthsis too
right ?
inside the
()
of the try
not the things inside the {}
u @Retention and @Target are not found by vscdoium
But you can put multiple things in the
()
do I need another dependency ?
separated by semi colon
nice
These are always included in Java
But you might need to import it
These are in
java.lang.annotation
try (int a = 3; int b = 3 * a)
is this possible
or nah
Retention (Java SE 21 & JDK 21)
declaration: module: java.base, package: java.lang.annotation, annotation type: Retention
not with
int
since you cannot close int
swell with resources u can close
my point is
But see here: https://stackoverflow.com/a/77113057/10871900
Stack Overflow
How to generate Custom Id in JPA
i want generate Custom Id in JPA it must be primary key of table.
there are many examples to create Custom Id using hibernate like this
i want same implementation but in JPA.The id must be alphanu...
can u make the second one
depend
on the first one
multiple things closed there
al;r ty
i came wantign help for @IdGeneratorType
I went out learning few things about try catch too
that's how stuff goes ;)
always keep learning
@dan1st maybe last question for today
@Override
This message has been formatted automatically. You can disable this using
/preferences
.why return Serializable
?
Because the old versions of Hibernate used
Serializable
how will springboot format this
into a varchar
?
ANd
Serializable
was commonly used for entities in the past
?im returning the next key
to be used in my database
it cant just put Serializable in my database
it has to be same type as the key in my database
will it just cast it
?
You can just return whatever type you want
You don't need
Serializable
herein the method im overriding says return type is serializable
Can you show your code?
I think it shouldn't be
public Serializable generate(SharedSessionContractImplementor session, Object object)
but public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType)
Oh you are using
IdentifierGenerator
?
Ah I see that one is possible as wel
just change public Serializable generate(...)
to public Object generate(...)
well which one should I use
its the only one u can use
either that one or
sequencestylegenerator
I think
IdentifierGenerator
is perfectly finebut sequencestylegenerator is just a implementation of identifiergenreator
use what works best for you
kk got it
this is my class
im not s ure if
is good usage
ig it's ok if it works
its not
String query = "SELECT " + sequenceName + ".NEXTVAL FROM dual";
must do it like this
well ideally not;)
Even if im using a preparedstatement
?
shouldnt that protect it
yes
against sql injection
PreparedStatement
only protects against SQL injections if you use string concatenationthis is string concatenation no
it is
it wouldn't be vulnerable if you can be sure that all components are safe
but you'd need to make sure that's actually the case
well isnt preparedstatement the one doing that
only with
?
not with +
im going to make an enum
that holds al available sequences
and it compares them with that
🤷♂️
but yeah everytime we add a sequence in the database I would need to modify
the enum
only ifit was possible to use some kind of factor y
or event listener for when a sequqnece is added
you could also get it from the classes
and make sure no user data sneaks in
but it might be a bit fragile
the more complex the higher the risk
@dan1st I ended up making this:
but u can see why its not a good approach
everytime we add a key we queue sequences and so on
im going to try and find a way in which
I can simply have a event
everytime a sequence is added
my app gets notified
actually the sequence name from the config should be trusted
so it should be fine in this case
but in other cases, you might have issues
or if you change the code in the future
why should it
?
The sequence name comes from your annotation, right?
and only from that annotation
yeha
but still rather be safe than sorry
im learning about jmx
so users have no chance of altering it
to see how to push events
from triggers
to my java app
everytime a sequence is added im going to instantiate it in a sequence holder class
and this would make it safe from SQL injection
and compare against that
in the case users can alter it
does this alternative im telling u seem fine
?
oh
using jmx
you have another possibility
you can create a single table holding all sequences
thats TableGeneration
it's already in spring
yes
yeah but then I cant use my custom logic
of prefix
What is your custom logic?
You can still make your own custom generation that uses a table internally
Note: I mean a single table for all sequences
I think the thing Spring normally tries to do is one table for each sequence
nah it does one table, like u have there
and then u gotta give it the name of the table
the sequence_name
and the column holding the current index
and the column holding the sequence name
yeah idk by heart
is it good practice to have a class holding sequence names, and then set a trigger for sequence adding to my db, and then pushing event with jmx to my applicaton and add the sequence name to the class holding them
I wouldn't say so
really why
At that point, I would just use something like table generation
lots of unnecessary complexity
and you can make your own table generation if necessary
but in terms of speed no ?
its easier to compare a string against 5 others
than to query a database from java app
everytime a key is needed/generated
?
sequenceNameHolder.contains(sequenceName)
if its the case then valid sequenceName
ah like that
yeah then everytime a sequence is added in my db
in the trigger psuh a jmx event to my java app
and do something like:
sequenceNameHolder.add(newSequenceName)
Though in this case it might be a better idea to generate the actual names of the sequence from the application
but that's your decision
oh yeah
i know what u mena
like create a sequence for the entitis
myself
To be honest, I don't think all of that complexity is necessary
i was just thinking in case of a bigger project where database is maanged by another team
Like just use the stuff Hibernate normally does
Well should your application have the permissions to change the DB structure/add sequences?
imo it should only insert, delete, update values from db
i find sequences to be more of an internal thing to the database itself
so managed by another team
values yes - but should it also have the permissions to create or drop sequences, tables, etc?
that's for the DB team to decide
yes exactly
so whenever they add a sequence
we should be abl to be informed by it in our java app
I have one advice for you: Don't introduce unnecessary complexity
im not gonna do all that
i did a simple regex
for handling
and then the name convention for sequences in the database is going to follow that regex
but i was thinking on a very high scale application
where millions of primary keys get added every day
queuing the db to see all sequence nams and comparing them is awful
and so maybe a jmx event will then be useful
Can't you use the normal sequence thing from Spring?
in my case though
no way
Like do you really need a custom thing for it?
no because I want to have:
prefix+subfix
for example for my person table:
PER1
PER2
PER3
PER4
Just because I want to not because I need to
would be nice if i could combine these
I think you can also create an
IdentityGenerator
that delegates to a SequenceGenerator
and adds a namethat would be mazing
ill try searching that up
those are both impelemntations of IdentifierGenerator
right ?
yes
that's how I found them
okay and then using my own annotation
can it @IdGeneratorType
one class
that implements or extends
one of those
not sure
you might need to make a custom
IdentifierGenerator
that just delegates to one of the otherswdym with delegates
something like that
mmm
I see
use a generator
within a generator
and the top generator all it does is add a string
Maybe you need to do something like
or whatever
but you'd need to try that
do whatever works for you
yeah
im going to try those out
nice brainstorming in here
Ended up doing this @dan1st
yeah and now im creating the sequence
from myj ava code
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.