Hibernate entity manager looking for tables in different schemas - java

I am implementing jpa persistence using hiberante-entity manager in a java web project.
I have set following property in in persistence.xml.
<property name="hibernate.hbm2ddl.auto" value="update"/>
I have a schema for each user. For e.g i have a schema for user1 and one for user2.
If the table 'ABC' is present in user1 schema but not in user2 schema & I deploy the application and it uses user2 db credentials, i get the message 'user1.ABC' table found so the 'ABC' table is not created in user2 schema.
When i tried with following property in the persistence.xml file the table is created in the user2 schema.
<property name="hibernate.hbm2ddl.auto" value="create"/>
My question is
why hibernate is searching in another schema i.e user1 if the application is using user2 db credentials? and
I don't want to create the schema every time the server is started so how can i avoid using
the value 'create'.
EDIT: Below is my persistence.xml file
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="XXXXXX" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.axonframework.saga.repository.jpa.SagaEntry</class>
<class>org.axonframework.saga.repository.jpa.AssociationValueEntry</class>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
Thanks in advance

I am also facing the same issue, and after digging a lot, get to know that the bug is related to the Mysql Connector.
After changing MySql Connector 6.0.5 to 5.1.28 It works fine for me.
I hope It can help you. Cheers

Has the same problem.
After set <property name="hibernate.default_schema" value="MY_SCHEMA"/> the problem has been solved.

Check if you are calling user1 and user2 in your Hibernate Sessionfactory.

If you want to handle several schemas properly then use multi-tenant per schema also if you want to update/create/migrate/handle columns/tables/schemas/databases then use flyway or liquibase
REFERENCES
Multitenancy https://vladmihalcea.com/hibernate-database-schema-multitenancy/
Flyway https://flywaydb.org
Liquibase https://www.liquibase.org

The Hibernate documentation is clear about this, you need to enable multi-tenant operations as described in this answer and this example.
Basically you have to declare multiple persistence units and have each point to a different schema. Each can then use different login credentials as well.
Hibernate documentation link
To summarise:
Define your persistence unit
Define your mapping files per persistence unit
When using JPA add the following:
3. Specifying tenant identifier from SessionFactory
4. Implement a MultiTenantConnectionProvider

Related

How create the database through Hibernate

In my spring project, i am using Hibernate to export my entity classes to a previously created database. But this will require the final user knows how to create a database in the Database manager system (Currently I am using Postgresql).
Is there any way of, given only the machine where the postgresql is installed (and the username and password, which is provided when the application is runned the first time), the Hibernate create a new database in the server if it doesn't exist?
If your configuration looks like this
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://host:port/database</property>
<property name="connection.username">username</property>
<property name="connection.password">password</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.show_sql">false</property>
<property name="hbm2ddl.auto">update</property>
</session-factory>
</hibernate-configuration>
Then the database will be created by Hibernate automatically.
Update:
Ok now I understand what you want. You want to start the Postgresql server with Hibernate. This is not possible. Hibernate does not do this.
You can do this with
Another script that starts with your application
A maven/ant target.
A build job
But the best solution is to use an in-memory database that does not need an external server (for example H2, or Java derby)
See also
Simulate CREATE DATABASE IF NOT EXISTS for PostgreSQL?
and
Postgres database create if not exists
Take a look of paramater hibernate.hbm2ddl.auto for your hibernate.cfg.xml file. I suggest you this link: Hibernate hbm2ddl.auto, possible values and what they do - any official explanation?
Run "CREATE DATABASE ..." (see http://www.postgresql.org/docs/9.0/static/sql-createdatabase.html) as a native SQL query ...
.createSQLQuery(" ... ").executeUpdate(); ...
Hibernate will - at least as far as I know - not create the database, only the tables in it.
I suppose you need to connect to postgresql via a second persistence unit/connection, because of the chicken-and-egg nature of this approach.

Log4j + OpenJPA = NoClassDefFoundError: javax/persistence/AttributeConverter

I'm trying to get log4j (I would also be happy to use any logging api as log as it is jpa persistent) use jpa appender.
My persistence.xml looks like this
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>org.apache.camel.processor.interceptor.jpa.JpaTraceEventMessage</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapAttributeConverter</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackAttributeConverter</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.MarkerAttributeConverter</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.MessageAttributeConverter</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.StackTraceElementAttributeConverter</class>
<class>org.apache.logging.log4j.core.appender.db.jpa.converter.ThrowableAttributeConverter</class>
<class>com.xxxxxx.lab.logging.ReportEntity</class>
<properties>
<property name="openjpa.jdbc.DBDictionary" value="org.apache.openjpa.jdbc.sql.HSQLDictionary"/>
<!-- value="buildSchema" to runtime forward map the DDL SQL; value="validate" makes no changes to the database -->
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
</properties>
</persistence-unit>
As per apidocs:
Many of the return types of LogEvent methods (e.g., StackTraceElement,
Message, Marker, Throwable, ThreadContext.ContextStack, and
Map) will not be recognized by the JPA provider. In
conjunction with #Convert, you can use the converters in the
org.apache.logging.log4j.core.appender.db.jpa.converter package to
convert these types to database columns.
So I added all necessary classes, but it still throws:
java.lang.NoClassDefFoundError: javax/persistence/AttributeConverter
AttributeConverter seems something new in JPA2.1. Are you sure your project is using JPA2.1 instead of any prior version?
Just curious, why are you so insists to use JPA for log persistence? There are plenty JDBC-based solution which works well. I don't see any reason for using JPA solution unless you are going to make use of the logging related entities in your application.

How to use Spring to manage connection to multiple databases

I have read other topics but didn't find a good and clear answer
What I'm trying to is to develop a web app which is able to:
1) Log/track user events in a seperate UI database which we connect via hibernate with the same database schema (maybe save connectionString to the different oracle databases)
2) At runtime when you log in you can choose an environment to connect to one of the three different oracle databases that have the same schema (but not the same data)
3) provide the correct DataSource with username and password (where to get this sensitive data? I would not keep this stored somewhere in the application)
I'm fairly new to the Spring framework. I found this link which could be a first lead.
Any suggestions?
Also using Spring 3.1 or 3.2, JDBC to query to my oracle database and hibernate mapping to my UI database. This sounds quite confusing so I have a picture:
infrastructure
Just create different DAOs each with a separate persistence-unit attached to them.
In your persistence.xml you can have multiple persistence-unit's each connecting to a different database.
Example:
public class Dao1{
#PersistenceContext(unitName="Database1")
protected EntityManager entityManager;
public class Dao2{
#PersistenceContext(unitName="Database2")
protected EntityManager entityManager;
<?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_1_0.xsd"
version="1.0">
<persistence-unit name="Database1">
<exclude-unlisted-classes />
<properties>
</properties>
</persistence-unit>
<persistence-unit name="Database2">
<exclude-unlisted-classes />
<properties>
</properties>
</persistence-unit>
</persistence>
The link you have mentioned in your post says following:
1) create different data sources pointing to different schema.
2) extends AbstractRoutingDataSource and create your own data source, override determineCurrentLookupKey method which will provide value of key. in your case it will return whatever user choose from UI. also in the bean definition of your custom data source pass all the data source as map with key as option available at UI.
3) Now assign this data source into your session factory bean.

HIbernate creating database table

I am in the process of learning JPA - Hibernate.
I am following this article
In Dog.java it is mentioned as #Table(name = "dog").
In persistence.xml I have the following
<property name="hibernate.hbm2ddl.auto" value="create"/>
Does this creates table dog in database? I have not created table Dog in database. So in production environment this could be dangerous though. In such scenarios what should be ideal value for hibernate.hbm2ddl.auto?
Any suggestions?
it's dangerous in all senses, your application user should not have DDL permissions (alter table, create tables) your application user should only do DML (SELECT, INSERT,UPDATE,DELETE, etc)
Yes, it does create the new table every time that your app is deployed. Better to use:
<property name="hibernate.hbm2ddl.auto" value="validate"/>
if you already have data in place.
Here are the possible options:
validate: validate the schema, makes no changes to the database.
update: update the schema.
create: creates the schema, destroying previous data(!)
create-drop: drop the schema at the end of the session(!)
Do not set <property name="hibernate.hbm2ddl.auto" value="create"/> in production, because whenever you restart the server, all tables will be deleted and newly created again. You can make use of this property(hibernate feature) if you are migrating from one database to another.
If you want to set then set <property name="hibernate.hbm2ddl.auto" value="update"/> in development(not in production). This will update the schema if there are any changes you have made in pojo classes(annotations).
Also check : Hibernate: hbm2ddl.auto=update in production?
Hibernate hbm2ddl.auto possible values and what they do?
Set it to "none" in a production environment.

HSQLdb permissions regarding OpenJPA

I'm (still) having loads of issues with HSQLdb & OpenJPA.
Exception in thread "main" <openjpa-1.2.0-r422266:683325 fatal store error> org.apache.openjpa.persistence.RollbackException: user lacks privilege or object not found: OPENJPA_SEQUENCE_TABLE {SELECT SEQUENCE_VALUE FROM PUBLIC.OPENJPA_SEQUENCE_TABLE WHERE ID = ?} [code=-5501, state=42501]
at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:523)
at model_layer.EntityManagerHelper.commit(EntityManagerHelper.java:46)
at HSQLdb_mvn_openJPA_autoTables.App.main(App.java:23)
The HSQLdb is running as a server process, bound to port 9001 at my local machine. The user is SA. It's configured as follows:
<persistence-unit name="HSQLdb_mvn_openJPA_autoTablesPU"
transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>model_layer.Testobjekt</class>
<class>model_layer.AbstractTestobjekt</class>
<properties>
<property name="openjpa.ConnectionUserName" value="SA" />
<property name="openjpa.ConnectionPassword" value=""/>
<property name="openjpa.ConnectionDriverName"
value="org.hsqldb.jdbc.JDBCDriver" />
<property name="openjpa.ConnectionURL"
value="jdbc:hsqldb:hsql://localhost:9001/mydb" />
<!--
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)" />
-->
</properties>
</persistence-unit>
I have made a successful connection with my ORM layer. I can create and connect to my EntityManager.
However each time I use
EntityManagerHelper.commit();
It fail with that error, which makes no sense to me. SA is the Standard Admin user I used to create the table. It should be able to persist as this user into hsqldb.
edit: after hours of debugging I found out why this fails. This kind of error message also appears if you do not set required table entries (NOT NULL). It didn't indicate that for me. It seems the OpenJPA layer mistakes not being able to insert statements because of missing entries for permission problems. I simply accepted the first answer therefore. Thanks for reading :)
I have the impressoin that HSQL has no rights to write its datafile in the configured directory.
That happens to me all the time when I test my server manually as root/Administrator and that when starting it as a daemon/service it changes to a less privileged user. Then the files are owned by another user as the server is running as.
It could be other reasons : on Windows I had it when another process (another server instance) was still clinging on to the files, or even when eclipse in its infinite wisdom decided to index the database.

Categories

Resources