I need to create a auto-incremented key (not a primary key) to use it as a file-name in spring-data
here what i tried:
#NotNull
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "BODY_FILE")
private long bodyFile;
in liquibase:
- column:
name: BODY_FILE
type: BIGINT
autoIncrement: true
but the field bodyfile is always 0.
#Generated value will ONLY work with a primary key.
It won't work with fields that are not a primary key.
It won't even work with the composite primary key.
But why not generated type can be applied for the non-primary field?
A possible answer is most of the older version of DB either does not support the AUTO_INCREMENT (Generated value) for the non-primary key field or If they support in a newer version that too has constraints- like for MySQL There can be only one AUTO_INCREMENT column per table, it must be indexed, and it cannot have a DEFAULT value.
So from where this zero comes from in your DB?
It is because of your datatype 'Long' its default value is getting stored in your DB.
For more details on #Generated value official documentation
Related
I am struggling to insert JPA mapped entities (via a Spring Data CrudRepository) into a table on SQL Server 2019 that has a primary key column of type UNIQUEIDENTIFIER and a default value of NEWID().
CREATE TABLE some_table
(
id UNIQUEIDENTIFIER not null primary key default NEWID(),
-- ...
)
The problem is that all variations I managed to get to work involve a UUID generator on the JPA/Hibernate side and I end up with two different UUID values in the table and the saved JPA entity object.
E.g. this mapping "works" in the sense that there is no error reported, but the saved entity object's id field contains a different UUID than what is saved as a PK value in the underlying table.
#Entity
#Table(name = "some_table")
public class MyEntity {
#Id
#Column(columnDefinition = "uniqueidentifier")
#GeneratedValue
private UUID id;
// ...
}
// id field not set
myEntityRepository.save(myEntity);
// if field set, but value differs from DB
Using #GeneratedValue (strategy = GenerationType.IDENTITY) yields a
org.hibernate.id.IdentifierGenerationException: unrecognized id type : uuid-binary -> java.util.UUID
despite the columndefinition.
How do I have to set up the mapping to either correctly pick up the UUID value generated by SQL Server or store the UUID value generated by a Hibernate generator strategy?
I am trying to migrate one of our services to Spring Boot 2.0.3.
While most of the tests are fine, one of them fails with error:
Caused by: org.h2.jdbc.JdbcSQLException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-197]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.Parser.readSequence(Parser.java:5970)
at org.h2.command.Parser.readTerm(Parser.java:3131)
at org.h2.command.Parser.readFactor(Parser.java:2587)
This is really confusing because all teh entities rely on the same generation id mechanism:
#GeneratedValue(strategy = GenerationType.AUTO)
It's a repository test and the repository itself is very straight-forward:
#Repository
public interface OrderDetailsRepository extends JpaRepository<OrderDetails, Long> {
OrderDetails findFirstByOrderIdOrderByIdDesc(String orderId);
}
What can possible go wrong here?
PS: And, yes, there is both orderId and Id field present in the entity.
When you choose #GeneratedValue(strategy = GenerationType.AUTO) Hibernate selects a generation strategy based on the database-specific dialect.
The problem in your case is hibernate can't find the HIBERNATE_SEQUENCE and thus can't create a new object for the sequence. Try adding a sequence like this and it should solve the problem, but could lead to inconsistencies with the data...
CREATE TABLE CUSTOMER(
id int primary key,
);
CREATE SEQUENCE HIBERNATE_SEQUENCE START WITH 1 INCREMENT BY 1;
I would suggest using the GenerationType.SEQUENCEand try to recreate your id pattern with your custom db sequence. You can read more about the GenerationType's
here
I encountered the same issue when written sample code for spring boot with h2. please find the details below of my findings.
In your entity class sequence is not given and check your table as well i.e. have you given AUTO_INCREMENT for primary key?
Please follow as below.
1. Check your ddl once and set auto_increment for primary key (see below for id)
CREATE TABLE EMPLOYEES (
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(250),
last_name VARCHAR(250),
email VARCHAR(250) DEFAULT NULL
);
Check your entity class and update primary key as below
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Please make a note that GenerationType is given IDENTITY you can give AUTO as well. Also if you are using h2 in-memory DB and table inserted few records while boot-start (if dml file available in resource) then hibernate insertion may give unique constraint because sequence 1,2,3..(depends on how many records inserted while startup) may have already used and as I said above hibernate will generate the sequence from 1 and will increment by 1 for every new insertion. So I would suggest don't insert records while boot startup better to insert programmatically.
For your learning you can use as given above but if it may use in production then better to implement your own logic to generate the sequence.
I had similar problem. If I understand things correctly It went down like this.
Before Spring upgrade I used AUTO - but it actually opted by default to IDENTITY strategy. I had auto incrementing PKs defined like this:
id BIGINT AUTO_INCREMENT PRIMARY KEY
Everything was fine.
With spring upgrade I had to specify H2 dialect:
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
I've read that if you use Hibernate as your persistence provider, it selects a generation strategy based on the database specific dialect. For H2 it probably opted for global sequence (that's what AUTO should mean according to JPA spec) - and it didn't find the sequence.
Solution is of course create the sequence (as suggested above) or manually override to originally auto selected IDENTITY.
CREATE SEQUENCE HIBERNATE_SEQUENCE START WITH 1 INCREMENT BY 1;
#GeneratedValue(strategy = GenerationType.IDENTITY)
I believe that root cause is that meaning of AUTO is/was not consistent/well defined/understood in time. Probably original 'auto' switch to IDENTITY was basically a bug.
I use Eclipse --> JPA Entities from Tables get generate entities from mysql database. All the tables' primary keys -- ids are int(11) AI PK. So instead of int or long, i am getting String for all the keys. What did i do wrong?
Thanks!
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="LOCATION_ID")
private String locationId;
Eclipse is not correctly parsing your primary key's data type (int(11)). As a result, Eclipse is unable to resolve the appropriate data type to Java type mapping. Because that mapping is missing, Eclipse defaults the datatype for primary key attributes to String. You could remove the display width attribute from your datatype (i.e. the (11)) and Eclipse should be able to more appropriately map the data type.
Just found out when generating the entity, click on the id and eclipselink will allow you to select the mapping type. Choose int instead of String will do the trick.
I have a table where I wish to replace a row when duplicate Primary (unique) key is found.
Create table History (
id varchar(5) not null,
name varcah(30),
primary key (id)
) engine=InnoDB character set utf8;
I'm using this with hibernate. id column is declared as #Id #Column(name="id", unique=true, nullable=false)
Help me change the above SQL, Hibernate annotations to allow REPLACE on duplicate primary key is found
The database Primary Key is not meant to be ever updated/replaced. There are workarounds but those are bad-practices.
You'd better use AUTO INCREMENT(MySQL), IDENTITY(MSSQL) or SEQUENCE(ORACLE, PostgreSQL) ID generation.
If you use MANUAL ID assignment and you get duplicate primary key violations, you have to check your current application concurrency design. Is the manual id assignment not thread-safe?
A database sequence or an AUTO-INCREMENT ID will save you from getting duplicate primary key violations.
I have the following definition for an id field in an entity that is mapped to a table in HSQLDB.
...
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "ID")
private Integer id;
...
But this does not seem to generate the an unique id; instead an attempt is made to insert null into the column which results in failure. If, I manually create a sequence and generation strategy to use that sequence then the data is persisted as expected.
Doesn't a generation strategy of auto imply that the provider (hibernate in this case) will automatically choose the correct approach and do all the heavy lifting as needed (create sequence, use a native approach or whatever works for that particular platform)? Is my understanding incorrect?
Doesn't a generation strategy of auto imply that the provider (hibernate in this case) will automatically choose the correct approach and do all the heavy lifting as needed (create sequence, use a native approach or whatever works for that particular platform)? Is my understanding incorrect?
It does in theory (it defaults to IDENTITY with HSQLDB) and it works for me. This begs the following questions:
What dialect are you using (just in case)?
How did you create the table?
Can you show the DDL (activate the logging of org.hibernate.tool.hbm2ddl if required)?
How do you insert (through Hibernate's API, right?)?
Here is a sample DDL for an entity Foo when using HSQLDB:
create table Foo (
id bigint generated by default as identity (start with 1),
bar varchar(100),
primary key (id)
)
I created the table using the HSQL DB manager. Just normal create table address... I had not set the id column as identity in my case - just set it as primary key.
Then you have your answer, use an IDENTITY column.
While Hibernate does choose the right strategy and does generate the appropriate INSERT statements (passing null into the id which is expected to be persisted into an IDENTITY column), it won't create or alter your physical model if you don't use the DDL generation and export capabilities.
I had the same issue when using a JpaSchemaGenerator utility class that I wrote.
When generating the schema for a org.hibernate.dialect.HSQLDialect (where I use a SEQUENCE to generate my unique IDs), I use the following Hibernate property:
hibernate.id.new_generator_mappings=true
This results in the following CREATE statement:
CREATE TABLE BATCH (
BAT_ID NUMBER(19,0) NOT NULL,
BAT_EXPIRY_DATE TIMESTAMP,
BAT_NUMBER VARCHAR2(255 CHAR),
BAT_MAT_ID NUMBER(19,0),
PRIMARY KEY (BAT_ID)
);
But when I use this same property in my utility class to generate a schema using the org.hibernate.dialect.HSQLDialect, I get the following CREATE statement:
CREATE TABLE BATCH (
BAT_ID BIGINT NOT NULL,
BAT_EXPIRY_DATE TIMESTAMP,
BAT_NUMBER VARCHAR(255),
BAT_MAT_ID BIGINT,
PRIMARY KEY (BAT_ID)
);
This would mean that if I created a Batch without an ID, it would not generate it for me and the NOT NULL constraint would cause an exception.
If I change the Hibernate property to the following:
hibernate.id.new_generator_mappings=false
Then it would generate the following CREATE statement:
CREATE TABLE BATCH (
BAT_ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
BAT_EXPIRY_DATE TIMESTAMP,
BAT_NUMBER VARCHAR(255),
BAT_MAT_ID BIGINT,
PRIMARY KEY (BAT_ID)
);
Which works perfectly when creating JPA entities with Hibernate.