JPA and toplink create-table on if they don't already exist? - java

Looks like jpa is something which makes me ask a lot of questions.
Having added this
<property name="toplink.ddl-generation" value="create-tables"/>
my JPA application always creates tables when running, which results in exceptions in case the tables already exist. I would like JPA to check if the tables already exist and if not create them, however I could not find a value for the property above which does this.
So if I just turn it off, is there a way to tell JPA manually at some point to create all the tables?
Update here's the exception I get
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'tags' already exists
Error Code: 1050
Call: CREATE TABLE tags (ID BIGINT AUTO_INCREMENT NOT NULL, NAME VARCHAR(255), OCCURRENCE INTEGER, PRIMARY KEY (ID))
MySQLSyntaxErrorException?! Now that's wrong for sure

According to http://www.oracle.com/technology/products/ias/toplink/JPA/essentials/toplink-jpa-extensions.html#Java2DBSchemaGen toplink does not have an option to update exiting tables, I'm not sure if I would trust it to do the right thing anyway.
You could configure toplink to generate a sql script that you then would have to execute manually to create all tables. The filenames and location can be configured like this:
<property name="toplink.ddl-generation" value="create-tables"/>
<property name="toplink.ddl-generation.output-mode" value="sql-script"/>
<property name="toplink.create-ddl-jdbc-file-name" value="createDDL.sql"/>
<property name="toplink.drop-ddl-jdbc-file-name" value="dropDDL.sql"/>
<property name="toplink.application-location" value="/tmp"/>

I would like [my] JPA [provider] to check if the tables already exist and if not create them, however I could not find a value for the property above which does this.
Weird, according to the TopLink Essentials documentation about the toplink.ddl-generation extension, create-table should leave existing table unchanged:
TopLink JPA Extensions for Schema Generation
Specify what Data Descriptor Language
(DDL) generation action you want for
your JPA entities. To specify the DDL
generation target, see
toplink.ddl-generation.output-mode.
Valid values: oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
none - do not generate DDL; no
schema is generated.
create-tables - create DDL for
non-existent tables; leave existing
tables unchanged (see also
toplink.create-ddl-jdbc-file-name).
drop-and-create-tables - create DDL for all tables; drop all existing
tables (see also
toplink.create-ddl-jdbc-file-name
and
toplink.drop-ddl-jdbc-file-name).
If you are using persistence outside
the EJB container and would like to
create the DDL files without creating
tables, additionally define a Java
system property INTERACT_WITH_DB and
set its value to false.

Liquibase (http://www.liquibase.org) is good at this. It takes some time to get fully used to it, but I think it's worth the effort.
The Liquibase-way is independent of which JPA persistence provider you use. Actually, it's even database agnostic.

Related

How to stop persistence from altering database, JPA

I am using camel and open jpa as persistent provider, but I don't want alter statements to be run on prduction.
Snapshot of persistence.xml
<persistence-unit name="camel-openjpa-oracle-alert" transaction-type="RESOURCE_LOCAL">
.
.
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=false)" />
</properties>
.
.
</persistence-unit>
What value we have to put for openjpa.jdbc.SynchronizeMappings, so that alter command are not executed.
I searched but was unable to find any such value.
It would be nice to know a little more about what you are doing and why you need to use SynchronizeMappings. The fact that you use ForeignKeys=true tells me you want OpenJPA to read you schema and determine if you have any database FKs defined (i.e. so OpenJPA knows about these FKs so it can order SQL properly to honor parent/child FK constraints). This is a perfectly valid use of SynchMappings. However, by using 'buildSchema', you are specifically telling OpenJPA to make "the database schema match your existing mappings"....this comment is lifted from this OpenJPA doc:
http://openjpa.apache.org/builds/1.2.3/apache-openjpa/docs/ref_guide_mapping.html#ref_guide_mapping_synch
Therefore, you are specifically telling OpenJPA to update your database schema. You can remove the 'buildSchema' if you don't want OpenJPA to update your schema to match your domain model. That is, try:
Or you could use 'validate' in place of 'buildSchema'....however, as the above doc states, OpenJPA will throw an exception if it finds a schema/domain mismatch which may not be what you want. I suggest you read the above doc, and look at the available options to you.
Thanks,
Heath Thomann

HIBERNATE: Auto append word into TABLE

hi I have an entity with this annotation
#Entity
#Table(name = "REPORT_WORK")
But for some reason hibernate keep saying Missing Table: REPORT_REPORT_WORK
I know that is the problem because of when I change the name to "REPORT_WORKX"
It will say Missing Table: REPORT_REPORT_WORKX
Has any encountered this issue before?
Update: when I change the name to JJJJ
It will say Missing Table: REPORT_JJJJ
so for some reason there it is auto appending REPORT_
Configuration:
hibernate.hbm2ddl.auto=validate
I suspect that the problem is your Hibernate configurations. Specifically, if you don't have an appropriate setting for hibernate.hbm2ddl.auto, Hibernate won't automatically update the database schema when you change your model.
(And if you don't want the updates to happen automatically, then you need to figure out what schema changes are needed, code them as SQL DDL, and run them manually.)
Can you post your persistence.xml (or equivalent)?
It sounds like you are implementing org.hibernate.cfg.NamingStrategy, get rid of this configuration.
Some additional info:
JPA (Hibernate) and custom table prefixes

how to create database schema with hibernate.cfg.xml

using
< property name="hbm2ddl.auto"> create< / property >
only creates the tables, and whenever a schema does not exist, hibernate fails to create the table because the schema does not exist.
Hibernate will not create the schema for you, but maybe you can tell your DBMS to run some script before hibernate starts to create the schema objects. I found something here and I think you can use it as a start point.

Add column in a table mapped using hibernate, without losing existing data

I have a table called Person which I have already mapped in hibernate I has already some data which I do not want to loose. I need to add new column called address, Any idea how to do that in hibernate ?
Thanks in Advance..
If you current tables are generated by Hibernate , you can simply add the address property in the java entity class for the address column . Then set the hibernate.hbm2ddl.auto property to update and hibernate will automatically create this column when the SessionFactory is built next time . Hibernate will not change any data store in your database when hibernate.hbm2ddl.auto is update.
Or , you can manually issue the SQL to alter the table structure and then add the address property in the java entity class for the address column.
Likely you are not forced to use Hibernate to create/update database schema. I assume you have something like this in your configuration:
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
Just change value to "validate", perform changes to the mappings and execute ALTER TABLE statements separately.
Other option is to use "update" to let Hibernate figure out how to update your table structure. I suggest to keep it in your hands and just execute DDL SQL manually.
You should also read this other SO question/answer: Hibernate: hbm2ddl.auto=update in production? before you set hibernate.hbm2ddl.auto to update.

Hibernate session.get() Problem with UUID string ID

I am having a problem with Hibernate.
The primary key of ID in mysql table is UUID style String. e.g.08fe2a75-5d40-4645-896d-aab2a3ac96b8
But I can not use session.get() to fetch out the data for some reason.
Software software=(Software)session.get(Software.class, id);
It seems ok with integer IDs.
Please advise
Activate the logging of the generated SQL to see what is happening exactly. This can be done by setting the following property in your Hibernate configuration:
<property name="hibernate.show_sql" value="true"/>
Or set the following category to debug in the configuration of your logging backend.
org.hibernate.SQL
Compare the generated query with the expected result (that works in your SQL client).
Reference
Hibernate Core reference guide
Section 3.5. "Logging"

Categories