Hibernate Identity column but not primary key - java

I have one sqlserver 2008 r2 datatable, it has one column autoId int identity(1,1), but it's not the primary key, another column varchar(20) is the one.
question is : how do i config the hbm file?
bellow is my config file,but it got errors when i try to save one instance.
"Cannot insert explicit value for identity column in table 'acct_info' when IDENTITY_INSERT is set to OFF."
<property name="autoId" type="int">
<column name="auto_id" not-null="true" unique="true" />
</property>

There can be two reasons , either you don't have sufficient privileges in DB for IDENTITY INSERT or there is mismatch in the mechanism by which you are trying to set an identifier in hibernate and DB layer.
You can have a look at your id generation strategy in hibernate definition file
In DB you can change to Set IDENTITY_INSERT to "ON"
Pick a different generator class

Related

Liquibase: addForeignKeyConstraint not supported for SQLite

Using the following changeset in liquibase to create a table with a foreign key is possible and works.
<changeSet author="cibn" context="initialSchema" id="initialSchema-edited-1.0.4">
<createTable tableName="prices">
<column name="articleId" type="String">
<constraints nullable="false" foreignKeyName="fk_articles_articleId" references="articles(articleId)"/>
</column>
...
</changeSet>
However, the addForeignKeyConstraint change after creation of the initial schema is not supported.
https://www.liquibase.org/documentation/changes/add_foreign_key_constraint.html
Why? and could this be changed?
I believe that's because ADD CONSTRAINT is not supported by SQLite for ALTER TABLE feature, and that's exactly what Liquibase does during addForeignKeyConstraint change.
Here's the documentation SQL Features That SQLite Does Not Implement
Only the RENAME TABLE, ADD COLUMN, and RENAME COLUMN variants of the ALTER TABLE command are supported. Other kinds of ALTER TABLE operations such as DROP COLUMN, ALTER COLUMN, ADD CONSTRAINT, and so forth are omitted.

Autoincrement in liquibase

How do i set the autoincrement property using 'startWith' on a column in PostgreSQL using liquibase??
For some reason it always starts from 1. I tried using a custom sequence but that didn't help either.
<column autoIncrement="true" startWith="100" name="id" type="bigint">
That's my current column definition which does not work.
EDIT:
I want to import data from csv using liquibase. I tried the following:
<changeSet author="author" id="createSequence">
<createSequence
incrementBy="1"
sequenceName="mytable_id_seq"
startValue="1000"/>
</changeSet>
</changeSet>
<changeSet author="author" id="1-mytable">
<createTable tableName="mytable">
<column name="id" type="BIGSERIAL" defaultValueComputed="nextval('mytable_id_seq')">
<constraints primaryKey="true" primaryKeyName="mytable_pkey"/>
</column>
</createTable>
<loadData encoding="UTF-8"
file="liquibase/data/mytable.csv"
separator=","
tableName="mytable">
</loadData>
</changeSet>
If i try this I receive the following error 'currval of sequence "table_id_seq" is not yet defined in this session' and I think that it uses the sequence from the public schema instead of what i have set to liquibase.
Another thing i tried was to update it manually:
ALTER SEQUENCE mytable_id_seq restart with 100;
In this case the sequence used was the one from the public schema, but i want to use the schema set to liquibase
Instead of using bigserial which is an autoincrementing bigint specific to postgres use bigint if you are going to be setting up your own increment and sequence.
"The data types smallserial, serial and bigserial are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases). In the current implementation, specifying:"
CREATE TABLE tablename (
colname SERIAL
);
is the same as
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
From here
https://www.postgresql.org/docs/12/datatype-numeric.html

Liquibase + Postgresql + Spring Jpa : Id auto increment issue

I have the following Id description in the entity:
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
Liquibase instruction for generate this id is following :
<column name="id" autoIncrement="true" type="INT">
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_entity"/>
</column>
Also I have liquibase scripts that insert to this table predefined values, e.g.
<insert tableName="entityTable" schemaName="public">
<column name="id">1</column>
<!- other fields-->
</insert>
The problem has appeared when I try to insert a new record without id using Jpa repository.
I got an error with a message like "duplicate id".
So, I understand that jpa(hibernate) doesn't use postgresql sequence for getting a new id value. And I don't want to include the sequence name to the entity's id description. I have hoped that this situation could be resolved by the postgresql itself.
And I wouldn't to use the 'hibernate_sequence'.
So, any idea how I can resolve this issue.
Thank you.
Liquibase's instruction autoIncrement="true" generates serial column for PostgreSQL. For serial column PostgreSQL will create a sequence with a name like tablename_colname_seq. Default column values will be assigned from this sequence.
But when you explicitly insert a value into serial column, it doesn't affect sequence generator, and its next value will not change. So it can generate a duplicate value, which is exactly your case.
To prevent this after you inserted explicit values you need to change the current value of a sequence generator either with ALTER SEQUENCE statement or with setval() function, e.g.:
ALTER SEQUENCE tablename_colname_seq RESTART WITH 42;
SELECT setval('tablename_colname_seq', (SELECT max(colname) FROM tablename));
This should fix the issue.
First create to table name example:
CREATE TABLE TABLE_NAME(ID_NAME SERIAL PRIMARY KEY NOT NULL);
Then in your annotation:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long nameAtribute;

Why is my Native generation strategy not creating an id on SQLServer only?

I have a Java WebApplication which uses Spring and Hibernate to create and populate a table. The table has a unique id which is set by the following Hibernate configuration:
<hibernate-mapping>
<class name="com.myco.TransactionImpl" table="myco_transaction">
<id name="id" type="java.lang.Integer">
<generator class="native">
<param name="sequence">id_column_sequence</param>
</generator>
</id>
<property name="user" type="java.lang.String">
<column name="tx_user" not-null="false" unique="false" />
</property>
...
</class>
</hibernate-mapping>
This works fine for all of our MySQL users. However one users who is using SQLServer 2008 Developer Edition seems to find that whenever the application attempts to put a value into this table, the system throws an error of the type:
WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 339, SQLState: S0001
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - DEFAULT or NULL are not allowed as explicit identity values.
ERROR Exception - Error attempting to save instance:
This error seems quite clear. The id has not been generated. But why?
We have tried to resolve this issue in-house using SQL Server 2014 and SQL Server Express 2008 however when we use either of those systems, the insert into the table works and the ids are automatically generated.
I am at a loss as to how to proceed. I believe that the problem is one of the following:
The user has somehow modified his database to not create sequences. If this is possible how do I go about reproducing this or asking the user how to check?
There is something fundamentally different about SQL Server 2008 Express and SQL Server 2008 Developer Edition.
The hibernate generation strategy is wrong for SQL Server 2008.
Any help or advice on how to proceed with this issue greatly appreciated.
Update :
Table Definition on the SQL Server 2008 machine:
CREATE TABLE [dbo].[myco_transaction](
[id] [int] IDENTITY(1,1) NOT NULL,
[tx_user] [varchar](255) NULL,
[tx_date] [numeric](19, 0) NOT NULL,
[restored_tx] [int] NULL,
[restored_maint_urn] [varchar](255) NULL,
[ds_action] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Update:
The user has stated this also fails on his version of SQL Server 2012 Developer Edition.
Since the identity is already defined on the table and working, you don't need to insert it. The table will automatically generate it upon insertion. If you are wanting to insert your own identity, you will need to run an IDENTITY_INSERT ON command before doing the insert. A word of warning, the insert will error if you are trying to insert an already generated identity. This type of operation is usually done on a fresh and empty table.

Mapping Hibernate : <composite-id> 3

I have a problem mapping to my webapp, I have a table (TacheTicket) contains two primary key and the mapping file I put the following code:
<hibernate-mapping>
<class name="com.model.TacheTicket" table="TACHETICKET">
<composite-id>
<key-property name="idTache" column ="idTache" type="com.model.Tache"/>
<key-property name="idTicket" column="idTicket" type="com.model.Ticket"/>
</composite-id>
</class>
</hibernate-mapping>
but when I execute the program this error appear :
org.hibernate.MappingException: Could not determine type for: com.model.Tache, at table: TACHETICKET, for columns: [org.hibernate.mapping.Column(idTache)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:269)
at org.hibernate.tuple.PropertyFactory.buildStandardProperty(PropertyFactory.java:120)
at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:45)
at org.hibernate.mapping.Component.buildType(Component.java:152)
at org.hibernate.mapping.Component.getType(Component.java:145)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:253)
at org.hibernate.mapping.RootClass.validate(RootClass.java:193)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1108)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1293)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:855)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:774)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1460)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1398)
... 21 more
Table definition.
CREATE TABLE gestionticket.tacheticket (
idTachet INT NOT NULL, idTicket INT NOT NULL,
PRIMARY KEY (idTachet, idTicket), INDEX idTicket_idx (idTicket ASC),
CONSTRAINT idTache FOREIGN KEY (idTachet) REFERENCES gestionticket.tache (idTache) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT idTicket FOREIGN KEY (idTicket) REFERENCES gestionticket.ticket (idTicket) ON DELETE NO ACTION ON UPDATE NO ACTION);
I think you are trying to create many to many relationship between tache and ticket.
You don't need configuration for the third table in hibernate.
You just have to configure the two tables with many-to-many tag.
Checkout this blog.
You need type="int" to agree with the table definition.

Categories

Resources