Hibernate configuration hbm2ddl.auto - java

I have such hibernate.cfg.xml:
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:postgresql://host:5432/app-dev</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="hbm2ddl.auto">validate</property>
...many mappings
</session-factory>
And the problem is that it's trying to update my database schema, but I want to disable that feature.
log from my application:
2015-08-29 16:29:57 ERROR SchemaUpdate:261 - HHH000388: Unsuccessful: create table myschema.public.mytable (id int4 not null, count int4, anotherid int4, onemoreid int4, primary key (id))
2015-08-29 16:29:58 ERROR SchemaUpdate:262 - ERROR: syntax error at or near "-" <<(mydatabase name contains "-" sign)
Position: 27
I also tried to leave hbm2ddl.auto tag empty or include 'none' value in it.

Remove the property <property name="hbm2ddl.auto">validate</property> entirely.
By default all options will be false and hibernate will not attempt to do any updates.

Remove Hibernatehbm2ddl.auto defaults to Hibernate not doing anything.
From the docs
The hbm2ddl.auto option turns on automatic generation of database
schemas directly into the database. This can also be turned off by
removing the configuration option, or redirected to a file with the
help of the SchemaExport Ant task.

Validate is the default property of hbm2ddl.auto, even if you dont specify hbm2ddl.auto property, then also it is by default validate. Secondly there is no such value as "none", there are only 4 options :
validate- it simply checks that table and its columns are existing in database or not an if a table does not exist or any column does not exist than Exception is thrown.
create - If the value is create than hibernate drops the table if it already exist and then creates a new table and executes the operation, this is not used in real time as the old data is lost from database.
update - If the values is update than hibernate uses existing table and if the table does not exist than creates a new table and executes operation. This is mostly and often used in real time and it is recommended.
create-drop - if the value is create-drop than hibernate creates a new table and after executing the operation it drops the table, this value is used while testing hibernate code.
Thanks
Njoy Coding

Related

Cannot apply Flyway migration for a PostgreSQL table

In my Java app, I have the following migration file:
-- code omitted for brevity
create table if not exists demo_table
(
id bigint not null,
"company" varchar(50) not null,
"name" varchar(50) not null
);
create unique index if not exists demo_table_uuid_company_key
on demo_table (uuid, "company");
create index if not exists demo_table_name_company_key
on demo_table ("name", "company");
Although I can run the sql part part part or at a time on PostgreSQL query window, when running my Java app, it throws the following error:
"Unable to create index (name, company) on table demo_table: database column 'name' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)"
I tried many thing e.g. removing the related migration row from flyway_schema_history table, delete indexes on demo_table, etc. But still the same error. If I try to remove double quotes ("") from name, it gives checksum error. So, as the name is reserve word, I use with double quotes. How can I fix it?
On the other hand, I am not sure if I should change these parameters on application.yml:
spring:
flyway:
enabled: true
jpa:
hibernate:
ddl-auto: update
Some minor issues with the script:
Missing comma on first column of create.
This column is also called id but the index references uuid.
Resolving this allowed the script to work perfectly for me (with the quotes as you have them)
If you make these changes and get a checksum error, please run flyway repair

Oracle->MSSQL: How to set identifier generator?

I'm migrating OracleDB11g to MSSQL2014.
Currently getting following error when trying to save new data:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert the value NULL into column 'ID', table 'testDB.FILE_SETTINGS';
column does not allow nulls. INSERT fails.
My interpretation is that this is caused as the "native" ID generator differs between Oracle & MSSQL (Sequence vs. Identity).
In Oracle we had small customization to HIBERNATE_SEQUENCE:
alter sequence hibernate_sequence increment by 5;
...but thats all.
hibernate-mapping is originally like this:
<id name="id" column="ID" type="java.lang.Long">
<generator class="native">
</generator>
</id>
In MSSQL I have tried it like this with no luck:
<id name="id" column="ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">HIBERNATE_SEQUENCE</param>
</generator>
</id>
And in MSSQL server I have sequence (migration tool created):
HIBERNATE_SEQUENCE in testDB->Views->sys.sequences
Also found in (migration tool created):
testDB->Views->INFORMATION_SCHEMA.SEQUENCES
How should this be done properly as I want to retain the same way to generate identity as was in Oracle? Something wrong in MSSQL or in hibernate settings?
Hibernate version is quite old: 2.1.8
Your interpretation of the error is wrong. This error tells you nothing about sequence. It tells you that your testDB.FILE_SETTINGS has id column defined as NOT NULL but you try to insert NULL value here.
I don't see your code but I think there is something like this:
create table dbo.MyTbl_wrong (id int NOT NULL, col1 varchar(100) );
insert into dbo.MyTbl_wrong(col1) values ('1 str'), ('2 str'), ('3 str');
Cannot insert the value NULL into column 'id', table
'db2.dbo.MyTbl_wrong'; column does not allow nulls. INSERT fails. The
statement has been terminated.
What you should do instead is to use sequence in the default for your id column like this:
create sequence dbo.MySeq
start with 1;
create table dbo.MyTbl (id int NOT NULL default(next value for dbo.MySeq), col1 varchar(100) );
insert into dbo.MyTbl(col1) values ('1 str'), ('2 str'), ('3 str');
--select *
--from dbo.MyTbl;
-------
--id col1
--1 1 str
--2 2 str
--3 3 str
Answering own question if some day someone has similar issues:
Apparently there was nothing wrong with the settings I mentioned in original question, only that hibernate 2.1.8 seemed not to support the SEQUENCE id genererator. Also old hibernate obviously did not support the needed SQLServer2012Dialect.
Ended up updating the hibernate version to 4.3.11 (with its dependencies). This version got selected as it required the least amount of refactoring.
I had some issues with the dependencies as this old project was not using Maven.
Also faced this error as any DB query was attempted:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
I found out that new hibernate version was defaulted to use lazy loading which was not supported in the old version. So I ended up fixing it with setting "lazy=false" in hibernate setting files.
You may see "org.hibernate.LazyInitializationException: could not initialize proxy - no Session" while upgrading from hibernate 2.1 to hibernate 3.0. You will suddenly find yourself puzzling what happened, it was working before update. Reasons is, Hibernate 3 introduced lazy loading as the default i.e. lazy="true". If you want it to work the same as before you can mark everything as lazy="false". Alternatively you'll have to start eagerly initialising your entities and associations.
Read more: http://javarevisited.blogspot.com/2014/04/orghibernatelazyinitializationException-Could-not-initialize-proxy-no-session-hibernate-java.html#ixzz56ahBmiBl

Hibernate : Insert column value from app instead of database

I have a column in my Database, called updateddate, which should get inserted with sysdate through application.
If my application code encounters some exception, even then I want this column value to be inserted with sysdate through database.
So, through SQL script, I have given this column default to sysdate.
Below is my hibernate hbm xml file,
<property name="updatedDate" type="timestamp">
<column name="UPDATED_DATE" ></column>
</property>
However, the column is not getting inserted through my application when there are no exceptions. It is getting updated through DB.
I am saying this by looking at the date format.
How to make the column to be inserted through application and only when it encounters exception it should get inserted through DB?
I tried insert=true. But didn't help.
I am not quite sure why you want to do this, but your application should set updatedDate to the current system date/time. The database default will only be applied if your application inserts a record with updatedDate = null.

Liquibase + H2 + Junit Primary Key Sequence starts over

I managed to integrate Liquibase into our Maven build to initialize a H2 inmemory database with a few enrys. Those rows have the primary key generated using a sequence table which works as expected (BigInt incremented values starting from 1).
My issue is that when i try to persist a new entity into that table from within a Junit integration test i get a "unique key constraint violation" because that new entity has the same primary key as the very first row inserted using the Liquibase changelog-xmls.
So the initialisation works perfectly fine as expected. The maven build uses the liquibase changelog-xmls
For now i just wipe the according tables completly before any integration tests with an own Runner... but that wont be a possibility in the furture. Its currently quite a chalange to investigate such issues since there is not yet much specific information on Liquibase available.
Update Workaround
While id prefer below answer using H2 brings up the problem that below changeset wont work because the required minValue is not supported.
<changeSet author="liquibase-docs" id="alterSequence-example">
<alterSequence
incrementBy="1"
maxValue="371717"
minValue="40"
ordered="true"
schemaName="public"
sequenceName="seq_id"/>
As a simple workaround i now just drop the existing sequence that was used to insert my testdata in a second changeSet:
<changeSet id="2" author="Me">
<dropSequence
sequenceName="SEQ_KEY_MY_TBL"/>
<createSequence
sequenceName="SEQ_KEY_MY_TBL"
incrementBy="1"
startValue="40"/>
</changeSet>
This way the values configured in the changelog-*.xml will be inserted using the sequence with an initial value of 1. I insert 30 rows so Keys 1-30 are used. After that the sequence gets dropped and recreated with a higher startValue. This way when persisting entities from within a Junit based integration Test the new entities will have primary keys starting from 40 and the previous unique constraint problem is solved.
Not H2 will probably soon release a version supporting minValue/maxValue since the according patch already exists.
Update:
Maybe we should mention this still is just a Workaround, anyone knows if H2 supports a Sequence with Liquibase that wont start over after DB-Init?
You should instruct liquibase to set the start value for those sequences to a value beyond those you have used for the entries you created. Liquibase has an alterSequence element for this. You can add such elements at the end of your current liquibase script.

Why is Hibernate generating this SQL query?

I'm using Hibernate and a MySql server. I use multiple databases as "namespaces" (e.g. users, transactions, logging etc.).
So, I configued Hibernate to NOT connect to a particular database :
url = jdbc:mysql://127.0.0.1/
The databases where tables are located are defined in the hbm files through the catalog attribute :
<class name="com.myApp.entities.User" table="user" schema="" catalog="users"> ...
When I want to load some data, everything works fine and Hibernate seems to generate the expected SQL queries (by using the catalog prefix in the table names) e.g. :
select id from users.user
However, when I try to add a new record, Hibernate don't use the from [catalog].[table_name] syntax anymore. So I get a MySQL error 'No database selected'.
select max(id) from user
Hibernate is trying the get the future id to create a new record, but it doesn't specify in which database is located the table, it should be :
select max(id) from users.user
Why is Hibernate generating this invalid query ? Have someone ever experienced this problem ?
You need to specify the schema for the generator. See this question on SO for a more detailed answer.

Categories