Good morning, I 'm trying to implement a multi-tenancy Java project ( Primefaces , EJBs , Hibernate 5 / JPA - Postgres ).
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.0.7.Final</version>
<scope>provided</scope>
</dependency>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence>
<persistence-unit name="myDS" transaction-type="JTA">
<jta-data-source>java:/myDS</jta-data-source>
<class>com.arkin.erpmodel.general.entities.AccountingDocumentType</class>
<class>com.arkin.erpmodel.general.entities.AccountingOperation</class>
<class>com.arkin.erpmodel.general.entities.AccountingYear</class>
<class>com.arkin.erpmodel.general.entities.AccountingYearPeriod</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.multiTenancy" value="SCHEMA"/>
<property name="hibernate.tenant_identifier_resolver" value="com.arkin.erpmodel.multitenancyprovider.SchemaResolver"/>
<property name="hibernate.multi_tenant_connection_provider" value="com.arkin.erpmodel.multitenancyprovider.MultiTenantProvider"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="org.hibernate.type" value="debug" />
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.infinispan.statistics" value="false" />
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.jdbc.batch_size" value="20"/>
<!-- Turn on entity and query cache statistics in the admin console -->
<property name="hibernate.generate_statistics" value="false" />
<!-- store entries in the cache in a more human friendly format - helps when interpreting logs -->
<property name="hibernate.cache.use_structured_entries" value="false" />
<!-- MultiTenancy -->
</properties>
</persistence-unit>
</persistence>
Maven Dependencies
I could help know why not recognize the MultiTenantConnectionProvider class?
If you check the readme in hibernate-entitymanager it says
Hibernate's JPA support has been merged into the hibernate-core
module, making this hibernate-entitymanager module obsolete. This
module will be removed in Hibernate ORM 6.0. It is only kept here for
various consumers that expect a static set of artifact names across a
number of Hibernate releases. See
https://hibernate.atlassian.net/browse/HHH-10823
Now, you need to use hibernate-core
The MultiTenantConnectionProvider is located in
org.hibernate.engine.jdbc.connections.spi package of `hibernate-core`
You can include this maven dependancy:-
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.7.Final</version>
</dependency>
Related
I have a java8 desktop app using GuicePersist, Hibernate, and HikariCP to communicate with a Postgres DB. I've had success getting my app to send/receive data to the DB using this META-INF/persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!-- A JPA Persistence Unit -->
<persistence-unit name="myJPAunit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.123fakestreet.bogus.tomb.impl.postgres.model.movies</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- SQL stuff -->
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<!-- hikari CP -->
<property name="hibernate.connection.provider_class" value="org.hibernate.hikaricp.internal.HikariCPConnectionProvider" />
<property name="hibernate.hikari.minimumIdle" value="20" />
<property name="hibernate.hikari.maximumPoolSize" value="100" />
<property name="hibernate.hikari.idleTimeout" value="30000" />
<property name="hibernate.hikari.dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource" />
<property name="hibernate.hikari.dataSource.url" value="jdbc:postgresql://192.168.100.75:5432/mpDb" />
<property name="hibernate.hikari.username" value="cowboy" />
<property name="hibernate.hikari.password" value="bebop" />
<!-- Disable the second-level cache -->
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<!-- Default is false for backwards compatibility. Should be used on all new projects -->
<property name="hibernate.id.new_generator_mappings" value="true"/>
</properties>
</persistence-unit>
</persistence>
The tricky part is configuring my Guice JpaPersistModule at runtime.
From what I can tell, I should be able to override properties in my META-INF/persistence.xml file by setting properties in a Map object, like this:
Map<String, String> properties = new HashMap<>();
properties.put("myJPAunit.hibernate.hikari.dataSource.url", "jdbc:postgresql://192.168.100.75:5432/mpDb");
properties.put("myJPAunit.hibernate.hikari.dataSource.user", "cowboy");
properties.put("myJPAunit.hibernate.hikari.dataSource.password", "bebop");
then jpaModule.properties(properties), and then pass this all to GuicePersist.
I've tried some different combinations of property names in the Map but so far I've had no luck. I've also looked at the pgsimpledatasource docs and the hikariCP docs regarding this topic, but still my datasource properties are not getting set.
Can somebody help? Thanks a bunch.
Try removing the persistence-unit name from the JPA properties, so instead of:
Map<String, String> properties = new HashMap<>();
properties.put("myJPAunit.hibernate.hikari.dataSource.url", "jdbc:postgresql://192.168.100.75:5432/mpDb");
properties.put( + "myJPAunit.hibernate.hikari.dataSource.user", "cowboy");
properties.put( + "myJPAunit.hibernate.hikari.dataSource.password", "bebop");
you should have this:
Map<String, String> properties = new HashMap<>();
properties.put("hibernate.hikari.dataSource.url", "jdbc:postgresql://192.168.100.75:5432/mpDb");
properties.put("hibernate.hikari.dataSource.user", "cowboy");
properties.put("hibernate.hikari.dataSource.password", "bebop");
I'm using JPA and have a persistence.xml with the following configuration:
<?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="odontonewPU">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="false" />
<!-- <property name="hibernate.hbm2ddl.auto" value="update" /> -->
<!-- C3P0 configuration -->
<property name="hibernate.connection.provider_class"
value="org.hibernate.connection.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.max_size" value="100" />
<property name="hibernate.c3p0.min_size" value="0" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="300" />
<property name="hibernate.c3p0.max_statements" value="0" />
<property name="hibernate.c3p0.timeout" value="100" />
</properties>
</persistence-unit>
</persistence>
The problem is that when i try to initialize my tomcat i got the following error:
691 [Thread-2] ERROR org.hibernate.connection.ConnectionProviderFactory - Could not instantiate connection provider
java.lang.ClassNotFoundException: org.hibernate.connection.C3P0ConnectionProvider
In my pom.xml (i use maven), i have the following dependency:
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
That class is part of hibernate-c3p0. You will need to add a dependency
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.2.7.Final</version>
</dependency>
or whichever version you need.
I'm currently using the following setup to create a schema in an embedded database before running my tests against it
In my application context
<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="classpath:createSchema.sql" />
</jdbc:embedded-database>
createSchema.sql
create schema ST_TEST AUTHORIZATION DBA;
hibernate properties
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.default_schema" value="ST_TEST"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
</properties>
My question is is this the best way to do this. Or can i use a different schema name in my properties? or set the schema name in the jdbc:embedded-database element
By default HSQL creates a schema called PUBLIC. source: HSQL documentation
Seeing as the schema name is never seen in the tests (named queries/entity manager to do the interactions) you can change the hibernate properties to use this PUBLIC schema
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.default_schema" value="PUBLIC"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
OR
just leave out the default_schema from the properties list and it uses PUBLIC anyway
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
You can use this code in your Base Testing class, and call it using #BeforeClass annotation (for Junit). I do it like this.
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
builder = builder.setType(EmbeddedDatabaseType.HSQL).addScript(
"createSchema.sql");
builder.setName("MyDatabase");
EmbeddedDatabase db = builder.build();
How to configure default table prefix in persistence configuration file. I'm using Spring's default configuration as follows:
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/MysqlDS</jta-data-source>
<properties>
<property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/spring-quickstart/persistence" />
<!-- Properties for Hibernate -->
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="false" />
</properties>
thanks
Looks like this SO question has the answer you seek.
Looks like what G. Bach refers to only allows you to change "metadata tables"?
Our application has a need to share an existing database table with another locally running application, and, so, I wish to refer to this table but skip generating the DDL for it. I also hoped to define the table in the application's schema as an alias or MySQL merge table, but I can add that to a manual script that will run before the generated schema script.
How can I specify that the create and alter table DDL for the shared_schema table are omitted from the myapp-schema-ddl.sql output?
From commons/src/main/java/com/company/shared/SharedSuperEntity.java:
#Entity
#Table(name="shared_entity", catalog = "shared_schema")
#Inheritance(strategy = InheritanceType.JOINED)
public class SharedSuperEntity {
// fields, etc...
}
From myapp/src/main/java/com/company/shared/SharedSuperEntity.java:
#Entity
#Table(name="local_entity", catalog = "local_schema")
public class LocalEntity extends SharedSuperEntity {
// fields, etc...
}
From myapp/src/main/resources/META_INF/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">
<persistence-unit name="MyAppPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/LocalDS</jta-data-source>
<class>com.company.shared.SharedSuperEntity</class>
<class>com.company.myapp.LocalEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<shared-cache-mode>NONE</shared-cache-mode>
<validation-mode>AUTO</validation-mode>
<properties>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.bytecode.use_reflection_optimizer" value="false" />
<property name="hibernate.default_batch_fetch_size" value="4" />
<property name="hibernate.default_entity_mode" value="pojo" />
<property name="hibernate.generate_statistics" value="false" />
<property name="hibernate.jdbc.batch_size" value="0" />
<property name="hibernate.jdbc.batch_versioned_data" value="true" />
<property name="hibernate.jdbc.fetch_size" value="0" />
<property name="hibernate.jdbc.use_get_generated_keys" value="false" />
<property name="hibernate.jdbc.use_scrollable_resultset" value="false" />
<property name="hibernate.jdbc.use_streams_for_binary" value="false" />
<property name="hibernate.hibernate.max_fetch_depth" value="3" />
<property name="hibernate.order_updates" value="true" />
<property name="hibernate.query.substitutions" value="true 1, false 0, yes 'Y', no 'N'" />
<property name="hibernate.use_identifer_rollback" value="true" />
<property name="hibernate.use_outer_join" value="false" />
<property name="hibernate.use_sql_comments" value="false" />
<property name="hibernate.id.new_generator_mappings" value="true" />
</properties>
</persistence-unit>
From within myapp/pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>hibernate3-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<components>
<component>
<name>hbm2ddl</name>
<implementation>jpaconfiguration</implementation>
</component>
</components>
<componentProperties>
<persistenceunit>MyAppPU</persistenceunit>
<outputfilename>myapp-schema-ddl.sql</outputfilename>
<drop>false</drop>
<create>true</create>
<export>false</export>
<format>true</format>
<jdk5>true</jdk5>
</componentProperties>
</configuration>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.0.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.0.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.0.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.16</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
</plugin>
I don't think Hibernate supports that directly. You could make two config files: one that lists all the mapped classes for runtime and one that omits the offending class for schema generation. Otherwise, you might look at some kind of post-processing, like a sed script, to remove the DDL after the fact.