I have the following in my code:
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Long id;
And, I noted when I have the #GeneratedValue it simply does not generate my MySql tables, yet without that annotation it generates the respective tables.
What are the key points I should be checking for ?
This is very tricky,as you might believe that you have define all the properties of hibernate properly and with the addition of #GeneratedValue annotation resulting a SQL Gram-mer error. Yet, I was able to resolve this by exploring the hibernate properties more carefully. Specifically look for the below properties in the hibernate configuration.
property name="hibernateProperties">
hibernate.dialect=${hibernate.dialect}
hibernate.hbm2ddl.auto=create
for the hibernate.dialect --> you should have org.hibernate.dialect.MySQL5InnoDBDialect
yet you might see, it also generates table for -> org.hibernate.dialect.SQLServerDialect in MySQL database, which push you to a conclusion that you have set the hibernate properties properly.
If any of your metadata annotation produces a grammer error, I strongly suggest you to check the hibernate properties
Thanks
Related
In my Spring Boot project I am opening access to an external database, where some tables are already defined.
I want to add some new #Entity classes and auto-update schema.
#Entity
#Table(name = "email")
public class Email {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="email")
private String email;
}
So I define a property for that in my application.properties file:
spring.jpa.hibernate.ddl-auto=update
But how can I prevent updating the schema, when I add a field to already existing #Entity class (e.g. accidentally), that maps "old" tables, which I must not change.
It is not possible to configure schema generation behavior at entity level.
To have better control over database schema evolution, it is recommended to use flyway or liquibase instead of relying on hibernate schema generation.
I built an application with Quarkus and I'm using Hibernate with Panache for the models. Everything goes well, the application starts, but when I call a webservice to get a list using Panache functionalities (.listAll()), I get an empty list and I see the following message in the console:
HHH000183: no persistent classes found for query class: from com.myproject.model.TeamEntity
My models are defined with #Entity annotations that should allow Hibernate to find by itself the entity mappings. Here is an example with the Team model:
#Entity
#Table(name = "TEAM")
public class TeamEntity extends PanacheEntityBase {
#Id
#GeneratedValue(strategy = SEQUENCE, generator = "TEAM_SEQ_GEN")
#SequenceGenerator(name = "TEAM_SEQ_GEN", sequenceName = "TEAM_SEQ", allocationSize = 10)
#Column(name = "ID_TEAM", nullable = false)
private int id;
#Column(name = "NAME", nullable = false)
private String name;
...
}
I don't have any persistence.xml file in the project, only the application.properties linked with Quarkus. Here are the relevant properties extracted from mine:
quarkus.datasource.db-kind=oracle
quarkus.datasource.jdbc.url=jdbc:oracle:thin:/#MYWALLET
%dev.quarkus.datasource.jdbc.url=jdbc:oracle:thin:MYUSER/MYPASSWORD#localhost:1521/SAA
quarkus.datasource.jdbc.driver=oracle.jdbc.OracleDriver
quarkus.datasource.jdbc.min-size=2
quarkus.datasource.jdbc.max-size=10
quarkus.datasource.jdbc.new-connection-sql=alter session set current_schema=MYSCHEMA
quarkus.hibernate-orm.dialect=org.hibernate.dialect.Oracle12cDialect
Does someone know where the problem could come from ? Hibernate should detect entities with annotations and use them in queries automatically.
It came out that the problem was on Quarkus Datasource configuration in the application.properties file. More particularly from this specific line to define the schema used at first connection (I have to admit that was not good looking):
quarkus.datasource.jdbc.new-connection-sql=alter session set current_schema=MYSCHEMA
Replacing the line above with the following solved the problem:
quarkus.hibernate-orm.database.default-schema=MYSCHEMA
In conclusion, I think Hibernate cannot find / does not take the entities defined if this property is not defined, maybe because it makes some kind of detection beforehand. That's only a supposition, if someone knows more precisely how Hibernate works for that specific case, I would be very interested !
I have created an entity with table name and column names.
I have also added the uniquekey constraint for a column name. But when I run, it shows the following error ;
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "alter table ingredient add constraint
UK_co7ro6kyijhfik027h0y4d3n3 unique (ingredient_name).
java.sql.SQLSyntaxErrorException: Specified key was too long; max key
length is 1000 bytes
After I run the spring boot application, I have tried to add the unique constraint manually in MySQL workbench. - DOES NOT WORK
I have added the below code - DOES NOT WORK
#Table(name = "ingredient", uniqueConstraints=#UniqueConstraint(name="uk_ingredient_name",columnNames="ingredient_name"))
#Column(name = "ingredient_name" ,unique = true)
private String ingredientName;
Tried to create a table manually in Mysql workbench and tried to alter the column name with unique key later. THIS WORKS. But I want hibernate to do this for me.
#Entity
#Table(name = "ingredient")
public class Ingredient {
#Id
#Column(name="ingredient_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "ingredient_name" ,unique = true)
private String ingredientName;
I want to save the ingredients without any repetitions. I do not want duplicate entries.
I have gone through other answers and none of those solutions helped me.
I tried adding length = 20 in the #column.
It works completely fine without any error.
Could you remove
,unique = true
from #Column annotation and try, it seems there is an hibernate bug .When using unique true it does not obey the naming strategy.
For more information look at this post
#UniqueConstraint and #Column(unique = true) in hibernate annotation
and this one
https://hibernate.atlassian.net/browse/HHH-11586
After removing the unique=true I am able to generate the unique constraint with the specified name that is 'uk_ingredient_name'.Since it is already specified in the #Table annotation.
The error you are getting is because hibernate is generating a unique constraint name which is hitting the allowed limit and it is not taking into the account the constraint name you have declared.
#Column(name="username", length=8, unique=true)
worked fine for me.
It turns out that the following example works when using mysql 5.x, however it doesn't when using an oracle 10g database.
Is there a way to define a unique identifier field that is independent of the database technology?
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private long id;
I have tested this in hibernate and the following exception occurs only when using Oracle:
org.hibernate.MappingException: Dialect does not support identity key generation
Using a database table is a portable way to generate identifiers.
The simplest way to use a table to generate identifiers is to specify TABLE as the generation strategy:
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
#Column(name="id")
private long id;
The provider will create the default table if you're using schema generation; if not, you must specify an existing table:
#TableGenerator(name="InvTab",
table="ID_GEN",
pkColumnName="ID_NAME",
valueColumnName="ID_VAL",
pkColumnValue="INV_GEN")
#Id
#GeneratedValue(generator="InvTab")
#Column(name="id")
private long id;
http://www.oracle.com/technology/products/ias/toplink/jpa/howto/id-generation.html#table
I have researched using GenerationType.AUTO and it does appear to be the better option. It allows the JPA implementation to choose whatever is best for the data storage system you are using.
I want some of mycoulmns in the JPA entity to take values from database during inserts/updates, i.e from Oracle sys_context, I believe JPA temporal annotation includes database generated timestamps during insert/updates, Is there any way I could create a custom annotation somewhat simailar to this or provide some default values during inserts/updates, can someone give few pointers if you faced this situation.
I want some of mycoulmns in the JPA entity to take values from database during inserts/updates
Configure the #Column to be not insertable and updatable and annotate the field with #Generated (Hibernate specific annotation). By doing so, Hibernate will fetch the value from the database after an insert, update. From the Reference Documentation:
2.4.3.5. Generated properties
Some properties are generated at
insert or update time by your
database. Hibernate can deal with such
properties and triggers a subsequent
select to read these properties.
#Entity
public class Antenna {
#Id public Integer id;
#Generated(GenerationTime.ALWAYS)
#Column(insertable = false, updatable = false)
public String longitude;
#Generated(GenerationTime.INSERT) #Column(insertable = false)
public String latitude;
}
Annotate your property as #Generated
You have to make sure your
insertability or updatability does not
conflict with the generation strategy
you have chosen. When
GenerationTime.INSERT is chosen, the
property must not contains insertable
columns, when GenerationTime.ALWAYS
is chosen, the property must not
contains insertable nor updatable
columns.
#Version properties cannot be
#Generated(INSERT) by design, it has
to be either NEVER or ALWAYS.