I have an Id field annotated with #GeneratedValue.
Is there any way to make hibernate autoincrement value that field if I pass negative value and not only zero?
I found the solution: its called hibernate iterceptor
You can also avoid the negative ID's using allocationSize:
#Id
#SequenceGenerator(name = "Template_SEQ", allocationSize=1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Template_SEQ")
I've tested with Hibernate 4.3.1.
Related
I'm stuck in some problem: I need to use sequences in PostgreSQL for generating ids. But when I save new object in table, it says that id is null
org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint
I use these annotations:
#SequenceGenerator(name = "fooGen", sequenceName = "FOO_SEQ", allocationSize = 1)
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fooGen")
#Column(columnDefinition = "numeric")
private BigInteger id;
And this worked fo Oracle. I've watched a lot of questions, but most used GenerationType.AUTO or GenerationType.IDENTITY, and solution was to use GenerationType.SEQUENCE. But I'm already using it.
I got this exception when trying to save my entity with repository method
fooRepository.saveAndFlush(entity);
My database is PostgreSQL 9.6.1.
I use
org.hibernate.dialect.PostgreSQL9Dialect
Sequence exists, I checked it. And hibernate.hbm2ddl.auto=validate would give me exception if it wouldn't be there.
Please, help me, where did I make a mistake?
I am using database schema:
<prop key="hibernate.default_schema">${jdbc.postgresql.schema}</prop>
maybe, this cause some problems?
Thanks in advance
Try to change type for id to Long like
#SequenceGenerator(name = "fooGen", sequenceName = "FOO_SEQ", allocationSize = 1)
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fooGen")
#Column(columnDefinition = "numeric")
private Long id;
This table has many-to-many relation, and table that connected two entities has its own id field. Hibernate had no mapped Java class for this table, and didn't set this id. And solution was to remove this field.
I saw this post (JPA Entity Lifecycle Events vs database trigger), but it didn't ask quite as explicitly as I am here:
Am I required to have a sequence AND a trigger for when I insert a row with a PK with a value of (null)?
Or will JPA somehow interpret the sequence annotations as a signal to grab .nextVal?
If you define a sequence on your primary key (#Id annotated field) and you map the sequence using the annotations #GeneratedValue and #SequenceGenerator, you can persist an entity with a null primary key. JPA will automatically call the sequence to get the next value (or get it from its cache).
The primary key declaration should look like.
#Id
#Column(name = "TABLE_PK")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_GENERATOR_NAME")
#SequenceGenerator(name = "SEQUENCE_GENERATOR", sequenceName = "SEQUENCE_NAME")
private Integer id;
I have a table with id like below, but hibernate uses org.hibernate.id.SequenceGenerator instead of SequenceHiLoGenerator for GenerationType.AUTO, how can I tell hibernate to use SequenceHiLoGenerator?
#Id
#SequenceGenerator(name="admin_seq", sequenceName="unique_id")
#GeneratedValue(strategy=GenerationType.AUTO, generator="admin_seq")
private Long id
If I use GenerationType.SEQUENCE, hibernate will use SequenceHiLoGenerator, but I need to use GenerationType.AUTO for compatibility with MySQL.
I have tried using #GenericGenerator, it works for Oracle but will be complained by MySQL: org.hibernate.dialect.MySQLDialect does not support sequences.
#GenericGenerator(name = "admin_seq", strategy = "org.hibernate.id.SequenceHiLoGenerator",
parameters = {
#Parameter(name = "sequence", value = "unique_id"),
#Parameter(name = "max_lo", value = "50") })
#GeneratedValue(strategy=GenerationType.AUTO, generator="admin_seq")
private Long id
I also tried using SequenceStyleGenerator by setting hibernate.id.new_generator_mappings=true in hibernate properties. It doesn't work either.
If you set hibernate.id.new_generator_mappings=true which uses SequenceStyleGenerator, it would work with Oracle. We have similar configuration in our project which works fine.
If you want to achieve bulk id retrieval(like 50 each time) to speed up the persist/save, the quirk here is you need to set allocationSize to 50 and also set your sequence Increment By to 50. 50 here is just a random number I choose, if you have massive persist, you can assign larger number. The most important thing here is the allocationSize in code and the Increment By in Database should MATCH.
The Oracle sql is something like
ALTER SEQUENCE YOUR_SEQUENCE_NAE INCREMENT BY 50;
The JPA entity ID field is like:
#SequenceGenerator(name = "YOUR_ID_GEN", sequenceName = "SEQ_YOUR_ID", allocationSize=50)
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "YOUR_ID_GEN")
#Column(name = "YOUR_ID")
public Long getYourId() {
return this.yourId;
}
strategy = GenerationType.AUTO should work against MySQL with an identity column even though you've configured a sequence too. The sequencegenerator will be used when running against Oracle, but ignored when running against MySQL.
In your persistence.xml you should also switch your hibernate.dialect property between the correct values for a Oracle dialect and a MySQL dialect.
I'm trying to annotate ID generators in Hibernate for an Oracle DB,
I've tried this so far:
a) #GeneratedValue(strategy=GenerationType.AUTO)
says id cannot be null when I try to persist the table
b) #GeneratedValue(strategy=GenerationType.SEQUENCE)
says Oracle doesn't support sequences (or something like that)
c) #GeneratedValue(strategy=GenerationType.IDENTITY)
says id cannot be null when I try to persist the table.
How should I annotate ID generators in Hibernate for an Oracle DB?
You can add generation strategy as Sequence and add sequence generator to your entity:
#SequenceGenerator(name = "GEN_TABLE_NAME", sequenceName = "SEQ_TABLE_NAME")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GEN_TABLE_NAME")
private Long id;
If you are not using hbm2dll.auto settings, you need to create sequence in your oracle database and specify it's name to "sequenceName" property.
I have the following Model:
public class Parameter extends Model {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long id;
}
The records created by save() look like this:
play=> select id from parameter;
id
----
1
2
3
4
5
21
(6 rows)
Is there a way that I can tell JPA to always increment the id by exactly one, instead of randomly jumping to 21?
What you are observing (jump to 21) is likely to be an implmentation detail of Ebean prior to 4.0.5. Ebean is using a 'fetch ahead' mechanism on the sequence. After 4.0.5 Ebean switched to use Postgres SERIAL by default (so by default you won't see this with Ebean/Postgres after 4.0.5). Refer: https://github.com/ebean-orm/avaje-ebeanorm/issues/97
That all said - 'incrementing EXACTLY by 1' is something you generally want to avoid as it becomes a concurrency issue (avoid making the autoincrement ID transactional as that introduces contention). When you need 'increment exactly by one' semantics (like cheque numbers etc) then you can look to create in batch in advance.
You should be able to achieve this by using #TableGenerator and allocationSize=1. An example code something like the following. You need to create a separate table to store the PK, additional work, but more portable than #GeneratedValue.
#TableGenerator(name="MAIN_PK_GEN", table="pk_gen", pkColumnName="GEN_NAME", valueColumnName="GEN_VALUE", pkColumnValue="MAIN_PK_GEN", allocationSize=1)
#Id #GeneratedValue(strategy=GenerationType.TABLE, generator="MAIN_PK_GEN" )
#Basic(optional = false)
#Column(name = "PK")
private Integer pk;
(But using allocationSize=1 may not be efficient)
See this tutorial for step by step explanation.
If you are using Oracle don't forget to add SequenceGenerator with an allocationSize of 1 :
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mysequence")
#SequenceGenerator(name = "mysequence", sequenceName = "mysequence", allocationSize = 1)
private Long id;