JPA / Hibernate : schema generation with multiple persistence units - java

I have an application that uses a set of JPA entities that are located in 2 different databases. I configured it with multiple persistence units.
The problem is that I want to auto-generate the schema using schema-generation, and all the entities are created in both databases.
I have in both PUs:
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
And, yes, I want to use the metadata to get the entities automatically. I do not want to provide a manual script, because I would need to keep it up to date with the entities.
Is there a way to mark which entity to be generated by which PU?
-edit: please be aware that adding "schema" property on #Table does not resolve the problem, because each PU will try to create the same entity in the right schema, and there will be errors because the tables will already exist.

Yes, you can do that. You need to list the entities under each persistant unit, and also DISABLE the auto discovery of the unlisted entities explicitly with <exclude-unlisted-classes>true</exclude-unlisted-classes>.
<!-- Unit 1 -->
<persistence-unit name="Unit1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.your.class.A</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.username" value=""/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
</properties>
</persistence-unit>
<!-- Unit 2 -->
<persistence-unit name="Unit2" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.your.class.B</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.username" value=""/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
</properties>
</persistence-unit>
Edit
If you are using annotations configuration, then
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setPackagesToScan("com.A");
And another factory for another entity manager with a different package name.

I found a way: I will use "schema" property in #Table annotation for each entity and then I would enable only one PU to auto generate the tables.

Related

What properties does persistence-unit have in apache openjpa?

I have not found any good documentation about it.
Example of persistence-unit in persistence.xml:
<persistence-unit name="DataLayer"
transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>myNonJtaDataSource</non-jta-data-source>
<properties>
<property
name="javax.persistence.schema-generation.database.action"
value="create" />
<property name="javax.persistence.jdbc.driver"
value="org.apache.derby.jdbc.ClientDriver" />
<property name="javax.persistence.jdbc.url" value=""/>
<property name="" value=""/>
<property name="" value=""/>
<property name="" value=""/>
</properties>
</persistence-unit>
I found some like: javax.persistence.schema-generation.database.action, etc., but I am looking for a (full?) list of "names" of those properties and maybe their possible values.
This is reference for persistence properties for JPA 2.X:
https://www.developer.com/java/ent/standard-persistence-properties-in-jpa-2.html
This is reference for openjpa: https://openjpa.apache.org/builds/3.0.0/apache-openjpa/docs/ref_guide_conf_openjpa.html
And here are also properties for Hibernate and EclipseLink: Properties reference for hibernate in persistence.xml

hibernate with JPA to generate entity in other schema

I have created two entities in my JAVA code one is Account entity, another is AccountLog entity. These two entities mapped to the corresponding table in same schema named testdb. We use hibernate and JPA to handle the insert/update and table generation.
Since the performance issue, I would like to separate the AccountLog into other schema named testdb_log. So that the AccountLog table will be generated in schema testdb_log and the next insert/update event will be stored in the schema testdb_log.
What is the best solution to handle the above cases? Add #table annotation with schema name? or others?
How to generate the entity to other schema?
For this entity, how to save/update this entity information to other schema?
I will probably use different persistence units in the persistence xml, something like this:
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="oneschema" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<properties>
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${datasource.baseurl}/SCHEMAONE" />
<property name="user" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
</properties>
</persistence-unit>
<persistence-unit name="anotherchema" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.company.AccountLog</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${datasource.baseurl}/SCHEMANOTHER" />
<property name="user" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
</properties>
</persistence-unit>
</persistence>
In the second persistence unit you declare explicitly what classes belong to it, so the entity manager will know how to deal with them.
Schema, connections, connection pools are usually transparent to the java code so you shouldn't change anything in java.

Different object models in same JPA persistence.xml

I'm using JPA to work with a couple of databases with different object model in them.
persistence.xml
<persistence-unit name="unit_1" transaction-type="RESOURCE_LOCAL">
<description>pu-pu-pi-du</description>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>my.package.items1.Class1_1</class>
<class>my.package.items1.Class1_2</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<!-- uncomment to show sql queries in System.out -->
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<!-- Envers -->
</properties>
</persistence-unit>
<persistence-unit name="unit_2" transaction-type="RESOURCE_LOCAL">
<description>Persistance config</description>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>my.package.items2.Class2_1</class>
<class>my.package.items2.Class2_2</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<!-- uncomment to show sql queries in System.out -->
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<!-- Envers -->
</properties>
</persistence-unit>
When I create factory this way:
EntityManagerFactory factory = Persistence.createEntityManagerFactory("unit_1", properties);
It works well, but updates the databast of unit_1 with all of the classes from unit_2. factory.metamodel.entities will contain all 4 classes:
my.package.items1.Class1_1
my.package.items1.Class1_2
my.package.items2.Class2_1
my.package.items2.Class2_2
And two more tables from model are added to database from unit_1.
How to explain JPA, that database of unit_1 has nothing common with unit_2 and I don't need its mappings?
Just add the following param after ''class'' tags in both of ''persistence-unit''
<exclude-unlisted-classes>true</exclude-unlisted-classes>

how to automatic create table in jpa persistence xml file?

I am using eclipse IDE.I also try following two .but failed..when i manually create table in my mysql database then my complete program run fine... I want create table automatic with respect to entity class.
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.hbm2ddl.auto">update</property>
here my persistence file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="JpaTest2" transaction-type="RESOURCE_LOCAL">
<class>com.jpa.Employee</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/hibernate"/>
<property name="javax.persistence.jdbc.user" value="umar"/>
<property name="javax.persistence.jdbc.password" value="umar"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
Dont use Hibernate specific options. JPA 2.1 provides
javax.persistence.schema-generation.database.action
that can be set to "create", "drop", "drop-and-create", "none".
That way you keep your code JPA implementation independent
Check your entity. Did you miss #Table annotation? The exception clearly says that the table is missing 'hibernate.employee':
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hibernate.employee' doesn't exist at ...
If you defined a naming strategy that prepends all tables with hibernate., then make sure that the tables are created in MySql.

name attribute doesn't seem to work in Field

As I am trying to map Entity to tables using JPA (Hibernate implementation) I found something confusing
when i use annotation on getter, things are OK
#Column(name = "main_battery_voltage", precision = 2)
public float getMainBatteryVoltage() {
return mainBatteryVoltage;
}
but When I try the same thing on field, field name is used and attribute
#Column(name = "main_battery_voltage", precision = 2)
private float mainBatteryVoltage;
System ignores name attribute, runs with column name mainBatteryVoltage in DB and consequently failed task.
I am using MySQL and this is the persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="SolarPersistenceUnit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.cs.solar.db.entity.User</class>
<class>com.cs.solar.db.entity.Lamp</class>
<class>com.cs.solar.db.entity.Project</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<!--<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>-->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/SOLAR"/>
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="admin" />
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.max_fetch_depth" value="3"/>
</properties>
</persistence-unit>
<persistence-unit name="TestSolar" />
</persistence>
Although it works now, I am curious what cause this problem, thank
You can find a short explanation here:
Hibernate Annotation Placement Question
The point is:
"the access type used by Hibernate will be field or property. The EJB3 spec requires that you declare annotations on the element type that will be accessed, i.e. the getter method if you use property access, the field if you use field access. Mixing EJB3 annotations in both fields and methods should be avoided. Hibernate will guess the access type..."

Categories