DDL generation and general persistence.xml settings (OpenJPA) - java

Summary
I'm trying to run a Java web application JPA 2.0 example. The example application was written to run in Glassfish, using EclipseLink as JPA provider.
I would like to convert it to run in TomEE with OpenJPA as the JPA provider, but I can't any detailed tutorials for getting up and running with OpenJPA.
Problem
I'm having trouble converting persistence.xml to work with OpenJPA instead of EclipseLink. More specifically, the given persistence.xml doesn't specify:
Entity classes. Are these necessary?
The desired JPA provider. Will the container default to something?
The JDBC driver. How do I specify an "in-memory" DB (just for initial testing purposes)?
Also:
How are the DDL generation properties expressed in OpenJPA? I wasn't able to find them the OpenJPA User Guide.
Details
Below is the EclipseLink persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="order" transaction-type="JTA">
<jta-data-source>jdbc/__default</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode"
value="both" />
</properties>
</persistence-unit>
</persistence>
I have the following Entity classes:
order.entity.LineItem
order.entity.LineItemKey
order.entity.Order
order.entity.Part
order.entity.PartKey
order.entity.Vendor
order.entity.VendorPart
Question
Does anyone know what the equivalent persistence.xml would look like for OpenJPA?
Alternatively, if anyone could point me to an OpenJPA tutorial that covers these issues that would be just as good

If you add the openjpa.jdbc.SynchronizeMappings property as shown below OpenJPA will auto-create all your tables, all your primary keys and all foreign keys exactly to match your objects
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
Alternatively, you can use EclipseLink in TomEE by just adding the EclipseLink jars to <CATALINA_HOME>/lib/
refer here for Common PersistenceProvider properties

Foreign key constraints
The next line does not create foreign keys:
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)"/>
Only creates schema and deletes content of a database.
But if you want create foreign keys, use the following lines:
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(foreignKeys=true,schemaAction='dropDB,add')"/>
<property name="openjpa.jdbc.SchemaFactory"
value="native(foreignKeys=true)" />
<property name="openjpa.jdbc.MappingDefaults"
value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/>
See generated SQL
In another way, if you want to see the SQL output:
<property name="openjpa.Log"
value="DefaultLevel=TRACE,SQL=TRACE" />
NOTE: In order to see the generated output in the TomEE console, you need to change the log level in the file loggin.properties with openjpa.level = FINEST
See more in http://openjpa.apache.org/faq.html

Related

Configuration of persistence.xml while using websphere 8.5.5.1

I'm coding an app that uses Servlet 3.0, Jsp, and JPA 2.0 and i'm deploying it into Websphere application server 8.5.
Since i already configured into the ibm websphere console, the data source and the jdbc driver, and the j2c authentification (i'm using oracle 11g as a database ). I dont know how my persistence.xml should look like, if i need to specify and add openJPA jars to my project.
For now anything i put into persistence.xml i'm having this issue :
Error 500: <openjpa-2.2.3-SNAPSHOT-r422266:1764177 fatal user error> org.apache.openjpa.persistence.ArgumentException
What should i do ? maybe i'm missing how JPA works
Thanks in advance
The OpenJPA jars should be provided by WebSphere and available to use for your application. There is a JPA sample available here: https://developer.ibm.com/wasdev/downloads/#asset/samples-Java_Persistence_API_JPA_Sample
In the sample, you can see an example of the persistence.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="jpasamplepersistenceunit">
<jta-data-source>java:comp/env/jdbc/samplejpadatasource</jta-data-source>
<non-jta-data-source>java:comp/env/jdbc/samplejpadatasourcenonjta</non-jta-data-source>
<class>wasdev.sample.jpa.Thing</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- These properties are creating the database on the fly. We are using them to avoid users having
to create a database to run the sample.
See also the create=true line in the datasource meta data. -->
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)" />
<property name="openjpa.jdbc.DBDictionary" value="derby" />
<!-- EclipseLink specific properties to create the database. They are only used if using the jpa-2.1 feature. -->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="both" />
</properties>
</persistence-unit>
</persistence>
I think your error is not caused by the OpenJPA jars not being available. It might be because your database is not configured correctly. Make sure your persistence.xml file refers to your datasources properly.

How to add missing columns in a multi-schema based multi-tenant web app using eclipselink

I'm developing a multi-tenant web app with "Shared Database/Separate Schemas" approach using java, jpa(eclipselink), mysql. My persistence file looks like:
<persistence-unit name="GroupBuilderPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.cache.shared.default" value="false"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/?"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
<--- Here goes other properties definition -->
</persistence-unit>
Now here is my EntityMangerFactory and EntityManager:
emfForTenant = Persistence.createEntityManagerFactory("GroupBuilderPU");
EntityManager em = emfForTenant.createEntityManager();
em.setProperty("eclipselink.tenant-id", schemaNameAsTenantId);
Its working fine untill I'm adding any new persistence column in any entity.
Like I've a Entity UserAccount where I've added a new column 'String rentalinfo' :
#Entity
#Multitenant(MultitenantType.TABLE_PER_TENANT)
#TenantTableDiscriminator(type = TenantTableDiscriminatorType.SCHEMA, contextProperty = PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT)
public class UserAccount implements Serializable {
...
private String rentalinfo;//Newly added column
...
}
Now after that this the following line is giving error:
em.createQuery("SELECT ua FROM UserAccount ua").getResultList();
The error is:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'RENTALINFO' in 'field list'
So what will be the solution for adding new column (extend table) in this approach?
You are getting this exception because the 'RENTALINFO' column does not exist on your UserAccount table. Under normal circumstances, setting "create-or-extend-tables" will have EclipseLink issue an ALTER to your existing table, adding the new column. However, it would appear ddl generation is not supported for MultitenantType.TABLE_PER_TENANT: https://wiki.eclipse.org/EclipseLink/DesignDocs/Multi-Tenancy/TablePerTenant
Not supported:
Schema generation will not be supported since it requires knowledge of all the tenants (schema's) and further to that, access provision must be set once the tables are created if using schema level table per tenant.
So there is no ALTER and your table does not have the column.
As a side note, you can turn on EclipseLink SQL logging using the following persistence properties:
<properties>
<property name="eclipselink.logging.level" value="ALL"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
</properties>
This way, you can see what queries EclipseLink is (or in this case, isn't) executing.

Java EE jta hibernate.hbm2ddl.import_files does not work

I try to import sql file when web application runs. I placed import.sql into src/main/resources/import.sql. Then I modified my persistence.xml by adding import_files directive:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.1"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jsp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="spPU" transaction-type="JTA">
<description>SP Persistence Unit</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:jboss/datasources/SpDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.hbm2ddl.import_files" value="import.sql"/>
</properties>
</persistence-unit>
</persistence>
But after redeploy or restart server nothing to uploads in database.
I use WildFly 8.1.0, Hibernate 4.3.5.Final, Database h2database 1.3.161.
I tried to remove blank lines from import.sql and change hibernate.hbm2ddl.auto to create-drop.
Any idea why import.sql does not load in database?
I had similar situation, please check if:
1) You can run your sql script manualy (No SQL errors are shown when error occurs during import)
2) Please make sure that all sql statements are single-lined, eg:
create table Table1{ column1, column2,etc.};
instead of
create table Table1{
col1 ..,
col2 ..,
}
I noticed these 2 issues when using import, hope this solves your problem too.
[UPDATE]
Thx to #vsapiha there is support for multiple lines sql:
<property name="hibernate.hbm2ddl.import_files_sql_extractor">org.hibernate.tool.hbm2ddl.M‌​ultipleLinesSqlCommandExtractor</property>
You don't need to specify the import files. Hibernate will look by default at WEB-INF/classes/import.sql, the place where it will be in your WAR if you place the file where you did. I always use WAR and never had to specify the location of it.
If you use JAR, the import goes in the root of the file, according to this link. (I never tried it though).

No Entity metadata found for the class

I'm back with the same problem ...
I'm trying to uses queries in my Cassandra DB with Kundera (Cassandra ORM), this queries work in an others project but when I try to do it in webapp (using tomcat 6.0), I got this error :
com.impetus.kundera.metadata.KunderaMetadataManager - No Entity metadata found for the class
=> JavaNullPointerException.
But when I leave the persistence.xml from my project I got an other error. (NoPersistence.xml found or something ... )
So, my project found Persistence.xml, but not my Entity class : fileCassandra.
You can see my persistence.xml :
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<!-- 192.168.3.107 -->
<persistence-unit name="cassandra_pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<class>net.***.common.db.***.FileCassandra</class>
<properties>
<property name="kundera.nodes" value="localhost"/>
<property name="kundera.port" value="9160"/>
<property name="kundera.keyspace" value="KunderaExamples"/>
<property name="kundera.dialect" value="cassandra"/>
<property name="kundera.client.lookup.class" value="com.impetus.client.cassandra.pelops.PelopsClientFactory" />
<property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider"/>
<!-- <property name="kundera.cache.config.resource" value="/ehcache-test.xml"/> -->
</properties>
</persistence-unit>
</persistence>
net..common.db..FileCassandra I must replace by * because it's name from my companie ;)
The same methods (include EntityManager) works in junit on other project, when I build my project in Tomcat, this error appears ...
This happens when you have multiple entries of the same class in your classpath.
The ideal place to have your entities is closest to the same class loader which loads kundera core and client(HBase, Cassandra etc.).
For example, if these kundera files are under WEB-INF/lib, you'd rather have your entities under the application where as if kundera files are on the applications lib folder, better bundle your entities in a jar and put them there (and remove the entities in your app).
Only issue which i can see is classes and persistence.xml location.
try to place persistence.xml within /WEB-INF/classes/META-INF/, Provided that your entity definitions are within classes folder!
-Vivek

Hibernate can't instantiate id generator in Spring project with multiple data sources

I have a Spring project using Hibernate with two data sources (db2 and sql-server).
As soon as I add
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SOME_SEQ")
to a column field in my entity class, I get a BeanCreationException when creating the sql-server EntityManagerFactory because org.hibernate.dialect.SQLServerDialect doesn't support sequences. The only place this entity is being used, though, is in a DAO that uses a db2 EntityManagerFactory which is using the appropriate dialect.
What am I missing?
Try it with GenerationType=AUTO instead of GenerationType=SEQUENCE.
#GeneratedValue(strategy = GenerationType.AUTO, generator = "SOME_SEQ")
With AUTO hibernate uses the best fitting generation strategy, which is sequences for some databases and autoincrement for others.
(N. B.: I never use annotations but I use mapping files. There <generator class="native"> works well for different database types. GenerationType=AUTO should be the same for annotations.)
Even I faced the same issue and solved it by adding the following option to the JPA persistence-unit configuration
<exclude-unlisted-classes>true</exclude-unlisted-classes>
This option forces the JPA provider to only scan the listed classes instead of the whole surrounding jar, etc.
So it now looks like -
<persistence-unit name="MSSQLBackedPersistenceUnit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/jdbc/MSSQLServerDS</jta-data-source>
<class>com.example.app.domain.MyEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2008Dialect" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>

Categories