Using same hibernate mapping files across multiple projects - java

There are several java SE apps using the same library and working with the same database via Hibernate (not JPA). Where do I put hibernate mapping files and hibernate config? (so what can be extracted to the library?)

Put everything that is common to all applications in the library, and everything related to a specific application (database URL, user, password, but maybe also caching options, etc.) outside of the library.
At then end, everything is loaded from the classpath. Whether the files are in one jar or another doesn't matter for Hibernate.
If you use annotations, most of the configuration will be in the entity classes anyway.

You might consider extracting all those mapping into single "DAO" project. Then you might add "DAO" dependency to all your apps. This way only "DAO" would communicate with DB and only "DAO" will require such mapping files.

Related

Modular Database Initialization

While working on a modular system architecture for an enterprise application I run into some problems with database initialization. We have a core library that provides base entities and base configuration. On top of this core several modules are build. They are pluggable and can have their own entities and configuration. Some characteristics:
Configuration, like system properties, resourcebundles, etc, are all stored in the database.
JPA is used to make the system database independent.
System runs on Java SE
Every module can bring its own tables, but they can also require to populate the core property table, or the core resourcebundle table. So somehow we need some mechanisme to run a DDL and DML initialization for the database. Some options:
Create simple sql scripts. Disadvantage is that they must be database independent and perhaps this is not the most developer friendly. Unless we can generate them with some DB diff tool?
Use Java classes to initialize via JPQL?
Store configuration in files? This avoids a lot (but not all) of configuration DML.
Use some tool like liquibase?
What would be the best practice for this (or a similar) problem?
Use a database for store all configuration data is the best option. Many products, such as WebSphere Portal or Liferay use a database to store the configuration data for each portlet or even for theme. Don't forget to include those that are used as part of an SOA and Business Rules.
Therefore, the use of SQL scripts is also the best choice. However, if you require very specific features of SQL, you may need to create several versions of same script for each database management system.
I am currently in an project that has the same idea of modules that add functionality to a core system.
Generally we are using maven and multiple src folders as well as maven profiles and different builds to be able to generate a deployable with different modules. (we do not have the necessity to push out single modules and install them later on - this might be different in your project. We just build different versions with different modules.)
Anyway, for the DB we are using liquibase. Firstly to manage the DB and the changes done to it. But also (and this might be helpful to you) to include/generate another SQL script that adds tables for the modules.
Each module has its own changeset-file that includes everything that is necessary for that module (also in different versions as the modules evolve through time). These can then be applied or not.
So, I think liquibase could also be useful in your case (even though it's main purpose is to manage DB changes).

Hibernate with Spring

I am having some problems getting Hibernate and Spring up and running. I have a web server project which makes use of several other projects which have persistent entities in them. The problem I have is that I get a ClassNotFoundException for an entity class that is stored within another jar inside of WEB-INF/libs.
Do I need to have a persistence.xml for each jar that contains entity classes?
Please let me know if you need to see any configuration files.
Depending on your set up there are probably a number of different ways to solve this - and none them usually feel idea (IMO).
The essential problem is to do with ClassLoader isolation. There are rules as to what the files within a jar can access.
In your particular case, the easiest way to solve it is probably to put the persistence.xml within the parent web project. If you are not using persistence xml, you need to bootstrap hibernate/spring from the web project.
The parent web project should have access to all the libraries within its WEB-INF/lib whereas each of the jars in the libs folder may not have access to each other.
You could set up another persistence.xml in each jar but they would not be composited together into one persistence unit. You would need to use a different pu depending on which entity you wanted.

Configuring Hibernate to use JPA-style configuration without going into EE

I am in the process of troubleshooting a recent translation of EJB code to native Hibernate code (painful process, since EJB spoiled me so much with its convenience).
One thing I find troublesome is that Hibernate keeps its entity declarations in a hbm.xml file and then the configurations in separate files. While this isn't necessarily a big issue, the Netbeans wizard doesn't really let the developer to just click a button, detect, all the entities on the fly, and update the configuration file.
With persistence.xml, however, I can do that easily by just adding the classes and forget about it. Another good thing is that persistence.xml stores pretty much everything needed for the ORM aside from the class-specific annotations (which I am keeping).
With that said, is there any way for me to have Hibernate to (1) stay off EE and (2) use persistence.xml to get the connection, mapping, etc?
Also, a related question - CriteriaQuery is apparently a Java EE thing. One thing I really like about using EJB is that there are strong compile-time contraints. For instance, I can put ClassName_.myAttribute directly as a parameter in a CriteriaQuery, whereas if I use the Hibernate native "Criteria" object, I have to use "my_attribute" instead, which is not subjected to compile time integrity checks (Note: ClassName_.myAttribute maps to "my_attribute" on the table).
So is there anyway to keep that compile-time integrity?
Thanks.
Hibernate EntityManager can be used outside of a Java EE container. See http://docs.jboss.org/hibernate/core/4.0/hem/en-US/html_single/#architecture-javase.
Moreover, even with the Hibernate native API, since you're using annotations, you don't need any hbm.xml file. Just a central Hibernate config file listing the entities and some Hibernate properties.

Hibernate configuration in libraries

Lets say I have two applications which both use Hibernate and both share some functionality, if I were to separate the shared functionality into a library what is the best way to structure the hibernate configuration?
I don't want to have to replicate the shared parts of the hibernate configuration in both my applications so is there a way I can save some configuration in the library (i.e. just the mapping elements for classes in the library) which is then loaded dynamically into the applications hibernate config at startup?
If you use spring, you could create an abstract bean with your base hibernate configuration, and then have your clients extend from that.
By using annotations, much of the mapping configuration ends up bound to the code. Library clients then only need to specify the package so that the hibernate annoatations are processed and added to the mapping configuration.
if you want to put all thge mapping elements in a jar & reuse them you can use the tag
<mapping jar="" />
here you pass the path & the name of the jar file (so the jar could be reused over & over again).
with this technique you will be able to share the hbm configs only..
if you need to share any other components there are different ways to do that.

Using Hibernate with Dynamic Eclipse Plug-ins

I have classes that are named exactly the same across different plug-ins that I use for my application, and I'd like to be able to configure them properly with Hibernate. The problem is that it looks like Hibernate dynamically generates a class' package name when trying to find a class when it's doing its mapping. With one plug-in this scheme works, but across multiple plug-ins it's not working. It looks like Hibernate gets confused when dealing with Hibernate configuration files across multiple plug-ins.
Is this because each plug-in has its own class-loader? What is the best way to proceed to make this work with the existing plug-ins and Hibernate?
The problem is, that every plugin has its own Classloader and Hibernate uses Reflection to find the right classes.
I have a very nice article at home about exactly this problem, but this one is in German. I will try to explain what you need to do.
In order to have the datastructure shared over several plugins, you have to put it in a plugin and enable a feature called buddy-policy.
Lets say you have a main-application-plugin which is initiating hibernate on startup, this plugin needs to "see" the classes from the datastructure-plugin. To do this the main-plugin sets its Buddy-Policy to "registered" and the datastructure-plugin registers itself as a "buddy". Unfortunately you have to do this all directly in the manifest file, at least in 3.3 there was no way to do this in the editor.
Once this buddy-policy works, Hibernate will also.
I looked up my old application and here is how I did it.
The main-application (toolseye.rcp) is dependent on the hibernate plugin (de.eye4eye.hibernate) and the datastructure-plugin (toolseye.datastructures)
The hibernate-plugin specifies its buddy-policy as "registered"
The datastructure-plugin registers itself to the hibernate-plugin
Here are the important lines:
Hibernate-plugin de.eye4eye.hibernate
Eclipse-BuddyPolicy: registered
Datastructure-plugin toolseye.datastructures
Eclipse-RegisterBuddy: de.eye4eye.hibernate
Put those line directly in the MANIFEST.MF
Both plugins need to reexport their packages in order that the main application or whatever layer you have in between can use them.
Hope that helped.
Just to make this complete.
Instead of using Hibernate, EclipseLink could be used as JPA-provider in a Eclipse RCP application. EclipseLink is the former TopLink from Oracle and has been choosen to be the reference implementation for JPA 2.
The point for an RCP is, that EclipseLink is available as OSGI-Bundles (org.eclipse.persistence.jpa), and due to that it can load classes from another plugin without an additional buddy-policy.
Currently I was playing around, using the following project structure (Model-View-Presenter Pattern). The names in the brackets specify the dependecy plugins (not all are included, only the ones related to this question)
rcp.mvp.view (rcp.mvp.presenter /
rcp.mvp.model)
rcp.mvp.presenter (rcp.mvp.data -
data reexports the model, so this is
not needed here) *
rcp.mvp.data (rcp.mvp.data.mysql /
rcp.mvp.model / javax.persistence /
org.eclipse.persistence.jpa)
rcp.mvp.data.mysql - provides only
the mysql-jdbc-driver. has to be
inside the classpath
rcp.mvp.model
In this scenario, the JPA provider in the data-plugin is able to load the classes from the model-plugin without a buddy-policy.
*Note, the presenter is not dependent on any JPA packages since this is encapsulated by DAOs (the main reason why to use them still)
Links
User Guide
RCP example (unfortunately not using DAOs)
EclipseLink conceptual Webinar from live.eclipse.org

Categories