I know it's possible to configure Hibernate in the 2 following ways:
hibernate.cfg.xml
persistence.xml - JPA - with specific hibenate configuration
when you add the provider like this:
org.hibernate.ejb.HibernatePersistence
But , I don't understand when should I use which ?
What should be the correct behavior?
Thanks!
You can use hibernate.cfg.xml when you want to use Hibernate in your project. When you create different queries (SELECT, INSERT, etc) you open session.
Session session = sessions.openSession();
where session is instance of org.hibernate.Session.
But as you can see we need sessions for creating session. Sessions is instance of org.hibernate.SessionSessionFactory. SessionFactory is global factory for concrete DB.
Session can be got by this action:
SessionFactory sessions = new Configuration().configure().buildSessionFactory();
where new Configuration().configure().buildSessionFactory() - parses hibernate.cfg.xml
Persistence.xml contains settings for using JPA in your project. Persistence units are defined in a persistence.xml file, which has to be located in the META-INF directory in the classpath. One persistence.xml file can include definitions for one or more persistence units. The portable way to instantiate an EntityManagerFactory in JPA (as explained in the JPA Overview section) requires a persistence unit.
See also: http://www.objectdb.com/java/jpa/entity/persistence-unit
Related
I'm using JPA quite often in command line java applications. With an application server I can easily link to an external configuration via <jta-data-source>jdbc/myDatabase</jta-data-source> in the persistence.xml. How is that possible without an application server? I could find some information about the attribute <non-jta-data-source/>. But how can I reference the values from an external file (probably in the properties format) in an elegant way? It would be nice to have as few as possible boilerplate code.
I've found an approach to this here, but I think there is a more elegant way:
JPA Desktop application
Now I'm working with this solution:
I need a properties file which looks like this:
javax.persistence.jdbc.url = jdbc:mysql://localhost:3306/database
javax.persistence.jdbc.user = root
javax.persistence.jdbc.password = root
javax.persistence.jdbc.driver = com.mysql.jdbc.Driver
Respecting this scheme allows me to use the values without any mapping later. I can then pass the values easily to cretae the EntityManagerFactory like this:
try (final InputStream jpaFileInput = Files.newInputStream(propFile)) {
final Properties properties = new Properties();
properties.load(jpaFileInput);
emf = Persistence.createEntityManagerFactory(PU_NAME, properties);
}
It is easy to use JPA with desktop applications. It's almost the same thing but you will need to manage transactions. As you have no application server the management of each and every transaction has to be done by you. Access to your JPA unit can be achieved through EntityManagerFactory.
Example:
EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("jpa-example");
EntityManager em = emFactory.getEntityManager();
em.getTransaction().begin();
em.persist(address);
em.getTransaction().commit();
You need to put your persistence.xml file under META-INF folder. You need to point out in your persistence config file that transaction type is RESOURCE_LOCAL. This is needed for running independently with no Application Server:
<persistence-unit name="jpa-example" transaction-type="RESOURCE_LOCAL">
You will however need to download and link the libraries in your project classpath. You will need the JTA jar and your persistence provider JARs which could be of Hibernate or any other vendor of your choosing. This could be achieved cleanly with Maven.
You may want to check this tutorial:
http://java.dzone.com/articles/jpa-tutorial-setting-jpa-java
Is there a way to set the EclipseLink properties (e.g. target database) in a place different from persistence.xml?
Rational: I have a JPA module defining the data structure and containing persistence.xml. The module might be used with different target databases. In a Java SE application one can set the eclipse link properties programmatically upon creation of EntityManagerFactory. However, when the JPA module is packaged in an EAR for the Glassfish application server the target database must be defined in persistence.xml ... or is there another way?
You can use a RESOURCE_LOCAL persistence unit and access it the same way through EntityManagerFactory.
Note: Although at first similar, this is not a duplicate of Using Spring, JPA with Hibernate to access multiple databases/datasources configured in Jboss
Dear Stackoverflow,
I had a spring-jpa with hibernate application running on jboss-4.2.1.GA and using a single database.
I now have a second spring-hibernate project bundled up in the same ear file with the project described above but it needs to use a second database. This second hibernate/spring project is set up with the database.properties and hibernate.cfg.xml files.
The two databases details are stored on jboss oracle-ds.xml file:
<datasources>
<local-tx-datasource>
<jndi-name>DefaultDS</jndi-name>
...
</local-tx-datasource>
<local-tx-datasource>
<jndi-name>SecondDS</jndi-name>
...
</local-tx-datasource>
</datasources>
My question is, in the second project, with objects for the second database and not the first one, how can I call sessionFactory for the second database whose details are stored on the oracle-ds.xml instead of using database.properties files?
I have seen an example calling
#Resource(mappedName = "java:SecondDS")
private DataSource secondDS;
...
java.sql.Connection conn = secondDS.getConnection();
If it is that easy to obtain a connection, that is only useful for prepared statements, how can I in get hold of the sessionFactory? Is there a similar approach?
All examples I have seen refer to database.properties and not the jboss ds.xml file.
Thanks in advance
There is several solution, depending on how you bind the data source to a presistance context, Spring way, JPA way or Hibernate way....
Spring
To link spring/hibernate application to JNDI data source, you will need to use JndiObjectFactoryBean
<bean id="serverDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/blah"/>
<property name="proxyInterface" value="javax.sql.DataSource"></property>
</bean>
This way you have a spring bean representing the JNDI data source. You will need to create 2 of them (one for each of you data source). They you need to inject the data source in your spring defined SessionFactory. The same can be use if you use Spring managed JPA entity manager.
JPA
If you are using JPA (session factory is hibernate not jpa...) you can also defined a jndi data source name in the corresponding persistance.xml file.
<persistence-unit name="sample">
<jta-data-source>java:/DefaultDS</jta-data-source>
...
</persistence-unit>
You need to use unitName parameter when injecting the entityManager:
#PersistenceContext(unitName="sample")
Hibernate
For hibernate.cfg.xml file you can specify the JNDI data source with this property
<property name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
The database.property should be removed to be sure the jndi data source is used.
These are only example, the final result will depend on how you made your plumbing.
I've been googling for this problem from last 2 days but havent found any proper solution. I am developing a desktop application with Hibernate. I am using AnnotationConfiguration for registering entities in hibernate. I am not creating xml mapping files as I am using persistence type entity beans. I've tried it with configuration xml file, properties file, programmatic registration of entity beans, but every time i am getting the same exception.
I've checked the entity class. Its importing javax.persistence.Entity; I've also tried adding #org.hibernate.annotations.Entity(mutable=true, dynamicInsert=true, dynamicUpdate=true) but no success.
When I pass incorrect path of one of the entity bean, hibernate initialization fails, which means before changing path, hibernate was picking up a correct entity file.
Is there any way to get a list of registered entities in hibernate configuration?
Have you declared the entities inside Your hibernate.cfg.xml file?
example:
<mapping class="test.User"/>
I am new to Spring and the bean concept, so sorry if asking the obviously.
I have set up a Java project and used the Hibernate framework to make my connections to the DB (using hibernate tool on eclipse, really recommended btw).
My basic setup was as follows:
some hibernate pojos (generated by Hibernate tools),
hibernate mapping files (hbm.xml files).
The configuration was set in hibernate.cfg.xml file placed at my root of the packages.
I initially setup a HibernateUtils class that gets a session from my sessionFactory.
some classes that act as Dao - creates the queries using the pojos and the hibernateUtils to get the session.
This was working fine with hibernate's powerful framework. Then I migrated to project to Spring MVC. From the various tutorials I read I understood that some changes need to be done in order to make things play nicely again. The main change is that the Spring FW now loads the beans by itself, therefore the following:
the pojos did not change, nor did the hbm.xml files
The configuration is no longer set at hibernate.cfg.xml - the Spring MVC FW loads it's own LocalSessionFactoryBean once I declared it in the XML files (Spring search for xmls as part of the initialization process). So I created a separate xml file called spring-hibernate.xml, that has the DB definition, the session factory bean and a hibernate template. To complete it, the xml file also declare the location of the Dao and the hbm files.
with hibernate template configured in the xml, there is a bean injection, therefore I changed the Dao files to add getter/setter to a hibernate template property. Then using this - the Dao class may create the db query.
All of this configuration works fine and I can get the Spring FW initialize the Dao classes (I put a sysout just to confirm that the Dao classes are injected with the hibernate template during MVC startup). Now my problem is - how to get access to the Dao bean instance created?
In my logic part, I get a hold of the bean as follows:
ClassPathXmlApplicationContext appContex = new ClassPathXmlApplicationContext(new String[] {"spring-hibernate.xml"});
UserUIDDao userUIDDao= (UserUIDDao)appContext.getBean("UserUIDDao");
Problem is - this is a NEW reference to a newly created bean and not the same one created during the spring MVC startup.
So my questions are: how to get a hold of the original bean created by the Spring init process? and - is my setup correct?
the pojos did not change, nor did the hbm.xml files
That's correct.
The configuration is no longer set at hibernate.cfg.xml - the Spring MVC FW loads it's own LocalSessionFactoryBean once I declared it in the XML files (Spring search for xmls as part of the initialization process).
You can choose to use Spring to configure Hibernate (but you could keep your hibernate.cfg.xml).
So I created a separate xml file called spring-hibernate.xml, that has the DB definition, the session factory bean and a hibernate template. To complete it, the xml file also declare the location of the Dao and the hbm files. with hibernate template configured in the xml, there is a bean injection, therefore I changed the Dao files to add getter/setter to a hibernate template property. Then using this - the Dao class may create the db query.
Using Spring's HibernateTemplate is one option, but you could also go template-less and just inject Hibernate's SessionFactory and use sessionFactory.getCurrentSession().
This is actually the officially recommended approach for new projects, check out So should you still use Spring's HibernateTemplate and/or JpaTemplate?? and the javadoc of HibernateTemplate.
Now my problem is - how to get access to the Dao bean instance created?
You inject it where needed (typically, in your services).
In my logic part, I get a hold of the bean as follows (...)
No, don't do this. This "service locator approach" actually defeats the point of a DI container like Spring. Configure Spring to inject your DAOs where needed.