Hibernate dynamic entity model - java

I am creating a Java application that utilizes a JPA annotated model - the core model -. On top of these entities, at runtime, I would like to add a jar file from an external source that contains some other JPA classes definitions and mappings. The imported archive might change its class structure and mappings, but it is the application's duty to refresh the entire schema when changed.
However, when trying to add the jar to hibernate Configuration, I get a
org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
The inner exception is related to the hibernate dialect:
org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
However, I am sure to have specified the hibernate.dialect property in the persistence.xml file. Below is the code I am using in my application:
org.hibernate.cfg.Configuration cfg = new org.hibernate.cfg.Configuration();
cfg.addJar(new File("path/to/jar.jar"));
cfg.buildSessionFactory();
What am I doing wrong?
Also, could you please tell me if you find this a good approach to create a dynamically updateable schema shared between multiple applications?

I managed to solve the problem. The main point is that, when using EntityManagerFactory (the JPA API), the hibernate persistence provider only reads the persistence.xml configuration files and loads the persistence units that are specified therein.
However, using a hibernate API configuration, hibernate does not read the persistence.xml files, so one will have to explicitly specify all aspects such as dialect, connection parameters etc in the hibernate.cfg.xml file.
However, I managed to work around this issue. Indeed, in the dynamically loaded jar file, one must export the folders (the META-INF especially) and configure a persistence.xml file in there too. However, naming two persistence units the same, their corresponding classes will not get merged and neither will any other properties. By default, hibernate will load the first found persistence unit and will treat the identically-named ones as different. So, I created a more flexible core schema that allows access to multiple persistence units, while caching them in something similar to dictionaries. Consequently, for each schema in my application, I will load the corresponding persistence unit while storing all of them in a dictionary-style container, allowing the application to get notified should any changes occur to the underlying jar file.

Related

How to set index base directory in hibernate full text search dynamically

I am trying to implement Hibernate full text search in my project and in this during login user select database which he/she wants to use. Means using dynamic data source routing. Index base directory path is in hibernate.properties file and it will be different for different database.
So now I want to change it at run time on the basis of selection of database by user. When we are creating session bean in spring then code is reading Hibernate properties. I searched a lot on internet and got an idea to override hibernate.properties file at run time. But I have some doubts:
How to override it for session factory, not for JPA
I think I don't need to reinitialize the session factory after overriding property. It will automatically read new directory on overriding .
Hibernate Search will read properties from all these places:
the JPA persistence.xml file
other JPA configuration (e.g. programmatic)
the Hibernate ORM hibernate.properties file
any other Hibernate ORM properties applying to the SessionFactory
Java System Properties
Environment variables
In short: don't set the index base in a fixed configuration property but set it dynamically in any way you set the other Hibernate ORM properties.

JPA Entity autodetection using class loader

I'm currently working on a project with a plugin system using Java's ServiceLoader. The plugin manager creates an URL classloader with the URLs of the jar-files, which is used to load the plugins. When creating the EntityManagerFactory, I set the eclipselink.classloader property to the created URL class loader, which should enfore the EntityManagerFactory to use my classloader for entity autodetection. However, Eclipselink fails to detect the entities in the plugins.
Eclipselink's logging (log level set to finest) does not mention the entities in the plugins at all, only the entities in the base project. I even tried pre-loading the entity and metamodel classes, but still no change.

JPA: Map multiple Oracle users on single persistence unit

I am using EclipseLink 2.5.2 (JPA 2.1), Spring 4.1.5, and I am deploying on Weblogic 12 and Oracle 12c.
I need to deploy my application to use 2 schemas (2 users on the same DB). The first contains the application data, the second contains lookup date which will never change. This is a hard requirement set by my client (the lookup schema may be used by other applications), however I know that they will be on the same Oracle instance. My JPA data model contains entities from both schemas and references between them. Likewise, at the DB level there are FKs in the data schema to the lookup schema.
I would like to:
map my entities in a way that will abstract away the fact that they reside on a different schema (prefixing the generated SQL queries with the user will be sufficient)
build a war file that is portable (no schema is hardcoded)
avoid synonyms, they are hard to maintain and the 2 schemas have a couple of metadata tables with the same name
My current solution:
I have a single persistence unit with all the entities from both schemas. I added an orm.xml for the lookup entities, where I define their schema at build time through Maven:
<entity class="my.package.lookup.ActionTaken">
<table name="ACTION_TAKEN" schema="${db.lookup.username}"/>
</entity>
I do this to avoid hardcoding the lookup schema in the #Table annotation on the lookup entities.
This works well, the generated SQL has the correct prefix for tables in the lookup schema. The problem is, However, as the lookup schema is defined at build time, the resulting war file is not portable.
Any thoughts on how to achieve this?
Some more thoughts:
I currently have a single persistence unit. I don't think that multiple persistence units would work well with entities from the first persistence unit referencing entities from the second.
I tried to have Spring filter the orm.xml file (i.e. I could define the lookup schema in a Spring profile), but Spring seems to be able to filter its own configuration only.
EclipseLink has is own Composite persistence unit, but I am ruling it out because:
Joins across tables in different data sources are not supported.
If you can use the same datasource to access the different schemas, then you can change the schema name using EclipseLink's customizers as described here: http://eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_customizer.htm .
You will need to change the table/schema name on both the entity's descriptor as well as any 1:M and M:M mappings that use a join table.

Referring entities from library to another library in JPA

I am using Hibernate 4.3.6.Final with JPA and Spring 4.0.6.RELEASE in my project with Java Configuration.
I have two jar files. module1.jar and module2.jar. module1.jar has some entities
and module2 has some entities. I can't use the module1.jar entity in module2.jar without using
persistent.xml and
<jar-file>module1.jar</jar-file>
Is it necessary to have persistent.xml as I am using
entityManagerFactoryBean.setPackagesToScan("com.mydomain") to scan all the entities from all jar files.
No, it is not necessary to use the persistence.xml if you are configuring Spring's entityManagerFactoryBean with setPackagesToScan().
From New Features and Enhancements in Spring 3.1:
3.1.12 JPA EntityManagerFactory bootstrapping without persistence.xml
In standard JPA, persistence units get defined through META-INF/persistence.xml files in specific jar files which will in turn get searched for #Entity classes. In many cases, persistence.xml does not contain more than a unit name and relies on defaults and/or external setup for all other concerns (such as the DataSource to use, etc). For that reason, Spring 3.1 provides an alternative: LocalContainerEntityManagerFactoryBean accepts a 'packagesToScan' property, specifying base packages to scan for #Entity classes. This is analogous to AnnotationSessionFactoryBean's property of the same name for native Hibernate setup, and also to Spring's component-scan feature for regular Spring beans. Effectively, this allows for XML-free JPA setup at the mere expense of specifying a base package for entity scanning: a particularly fine match for Spring applications which rely on component scanning for Spring beans as well, possibly even bootstrapped using a code-based Servlet 3.0 initializer.

How to Get Spring JPA, Hibernate, and OSGi to Play Nice?

I am attempting to get a WAR file to run inside of a Karaf OSGi container. The application runs correctly in stand-alone Jetty 6.1.26, but when the application is run inside of Karaf, I get the following exception and the Karaf instance freezes:
WARN org.hibernate.ejb.packaging.InputStreamZippedJarVisitor - Unable to find
file (ignored): bundle://125.0:240/ java.lang.NullPointerException: in is null
Note that the application is not relying on Hibernate in a separate OSGi bundle; it includes the hibernate jars in WEB-INF/lib.
I have examined the information on this post: Equinox (OSGi) and JPA/Hibernate - Finding Entities. However, the application is using JPA, rather than using Hibernate directly. The application's configuration is much like the 2nd option found in this post: Difference between configuring data source in persistence.xml and in spring configuration files. As such, I don't have a handle on a Hibernate SessionFactory that allows me to set the annotatedClasses property.
Any ideas on how to get past the exception?
I worked in parallel with the author and I'll post our solution here for anyone that runs into this in the future.
The exception is thrown because Hibernate tries to unzip it's jar to look for the persistence classes. As other posts mention, OSGi does not allow Hibernate to act like a classloader, so this fails. The solution was specifying all of the classes that it needed to load by hand and then telling it not to try to load anything else.
We used a persistence.xml file and an orm.xml file (we used default names so we didn't have to specify either in our applicationContext.xml).
Our persistence.xml file simply pointed to the orm.xml using the <mapping-file> tag. It also included the <exclude-unlisted-classes/> tag to keep hibernate from trying to load additional classes.
Our orm.xml file used <entity class="path.to.my.class" metadata-complete="false"/> to call out every entity class that we needed to load. The metadata-complete part tells hibernate to use the annotations found in the class to complete the configuration.

Categories