ghill wrote:
I am trying to use Hibernate and JPA in an Eclipse RCP application to provide the necessary persistence layer. I have seen some references to packaging hibernate as a plug-in for exclipse using "buddy loading", but can find no reference to doing something similar for JPA. Does JPA need to be similarly wrapped? Are there any supported "pre-wrapped" plug-ins for Hibernate and JPA out there?
Thanks in advance,
Graham
Using Hibernate in an extra "plugin" is what I also did including the buddy loading stuff.
There is nothing special to do if you want to use JPA.
I'll add a lot of details and there might be some mistakes as I also just started with Eclipse RCP, JPA and Hibernate but I hope this helps to get you and other people started.
Edit 2008-03-26: Moved log4j.properties from Hibernate-plugin to DataModel-plugin and now Hibernate does find the file. I have no idea why it couldn't find it when it's placed at the Plugin with the Hibernate libs.
I also added a tip at the bottom if you have problems generating JPA classes from existing database tables.
Here is what I did so far:
-Created Main RCP Application Plugin
-Created "HibernateAccessor" Plugin (All needed hibernate files are in a lib directory; used packages: hibernate, hibernate-annotations,...)
-Created "HSQLDBAccessor" Plugin (Database driver)
-Created "DataModel" Plugin (I could have included the datamodel into the main application but didn't want to do that, as other apps might later have to access this datamodel, so it's better to seperate it)
Now to the details...
The Hibernate-Plugin (doesn't use an Activator class)
The MANIFEST.MF (META-INF directory) includes several tabs which I'll describe here...
1.) Overview: Includes the basic plugin information (Name,...)
2.) Dependencies: As "required plug-ins" I added my Database Plugin "HSQLDBAccessor"
3.) Runtime:
-Exported Packages: Includes javax.persistence, javax.persistence.spi and all org.hibernate.* + org.jboss.* (most likely more then required but better save than sorry)
-Classpath: I added not just the "lib" directory but selected each of the *.jar files that I could find there (selecting the "lib" should also work)
4.) Extensions: Nothing to do here
5.) Extension Points: Nothing to do here
6.) Build: This might not be correct but I selected at "Binary Build" only META-INF, build-properties and the lib directory.
At the "Source Build" also also selected META-INF and lib.
7.) MANIFEST.MF:
The Hibernate plugin uses the Buddy loading stuff...so I added at the end of the MANIFEST.MF the following two lines:
Code:
Eclipse-BuddyPolicy: registered
Eclipse-LazyStart: false
The DataModel-Plugin (uses Activator class)The MANIFEST.MF (META-INF directory) includes several tabs which I'll describe here...
I also placed my "persistence.xml" file in the META-INF directory of this plugin.
1.) Overview: Basic plugin information
2.) Dependencies: As "required plug-ins" I added org.eclipse.core.runtime and hibernateaccessor
3.) Runtime: Nothing to do
4.) Extensions: Nothing to do
5.) Extension Points: Nothing to do
6.) Build: As "Binary Build" I only checked META-INF and log4j.properties (used a log4j.properties sample I found somewhere: added content below) as "Source Build" I checked .classpath, .project, META-INF, build.properties, src and log4j.properties.
7.) MANIFEST.MF: At the end I added the hibernate plugin as buddy:
Code:
Eclipse-RegisterBuddy: midarchrepo.hibernateaccessor
Eclipse-LazyStart: true
This should be enough to create your data objects inside the "DataModel" plugin. The class should look like this:
Code:
package your.package;
import java.io.Serializable;
import javax.persistence.*;
@Entity
public class YourJPAClass extends Serializable {
/**
* ID stored in the database
*/
@Id @GeneratedValue
protected Integer styleId;
/**
* Default constructor
*/
public YourJPAClass() {
}
public Integer getStyleId() {
return styleId;
}
public void setStyleId(Integer styleId) {
this.styleId = styleId;
}
}
The main application-plugin:1.) Overview: The usual stuff.
2.) Dependencies: As "Required plug-ins" I added org.eclipse.ui, org.eclipse.core.runtime.compatibility.auth (have some error because of this one), org.eclipse.core.runtime, hsqldbaccessor, datamodel.
As "Imported Packages" I added all the "org.hibernate.*" packages (important...as I start the provider at the core plugin - see below)!
3.) Runtime: Depends on your needs..I have some exported packages here but they are special for my app.
4.) Extensions: org.eclipse.core.runtime.applications, org.eclipse.ui.perspectives, org.eclipse.runtime.products (you may not need to use them as well)
ID: application (default???)
5.) Extension point: None so far
6.) Build: As you need...
[...]
I my application activator class I use this after I started the database:
Code:
[..]
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends AbstractUIPlugin {
// Session factory (which is e.g. Hibernate or Toplink)
SessionFactory sessionFactory;
[..]
public void start(BundleContext context) throws Exception {
[..]
AnnotationConfiguration config = new AnnotationConfiguration();
config.addResource("/META-INF/persistence.xml"); // location of persistence.xml
// with config.setProperty("...", "...") you can overwrite settings from the persistence.xml
sessionFactory = config.buildSessionFactory();
}
[..]
}
persistence.xml (you have to remove some of the comments!!)Code:
<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="pu-midarchrepo" transaction-type="JTA"> -->
<persistence-unit name="pu-midarchrepo" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- Only needed for JNDI database referencation...otherwise use JDBC... -->
<!-- <jta-data-source>java:/DefaultDS</jta-data-source> -->
<mapping-file>ormap.xml</mapping-file>
<!-- Only needed for J2EE not for J2SE -->
<!-- <jar-file>MyApp.jar</jar-file> -->
<!-- Definition of classes that use JPA Annotations (DataModel classes) -->
<class>your.package.YourJPAClass</class>
<properties>
<!-- Only needed for JDBC database referencation ...if using JNDI database see definition above -->
<!-- Database connection settings -->
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<!-- JDBC connection pool (use the built-in) -->
<!-- <property name="connection.pool_size" value="1"/> -->
<!-- SQL dialect -->
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<!-- Enable Hibernate's automatic session context management -->
<!-- <property name="current_session_context_class">thread</property> -->
<!-- Disable the second-level cache -->
<!-- <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> -->
<!-- Echo all executed SQL to stdout -->
<!-- <property name="show_sql">true</property> -->
</properties>
</persistence-unit>
</persistence>
log4j.propertiesCode:
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=warn, stdout
#log4j.logger.org.hibernate=info
log4j.logger.org.hibernate=debug
### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug
### log just the SQL
#log4j.logger.org.hibernate.SQL=debug
### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug
### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug
### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug
### log cache activity ###
#log4j.logger.org.hibernate.cache=debug
### log transaction activity
#log4j.logger.org.hibernate.transaction=debug
### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug
### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
Tip: I found the
BEA Workbench application (Eclipse with integrated BEA plugins) pretty nice to generate JPA enabled Java classes from existing Database tables. You can download a demo (round about 500 MB) from the bea.com website. There is also a nice screen demo available which shows the application development with Adobe Flex. When you installed the product you can request a demo key (runs 30 days). You just have to create a new database connection and a web application with a JPA fragment. Then you can select the database tables from which you want to create JPA annotated Java classes. These might need some tweaks but you are more then halfway there with a few clicks.., it's really great. A also tested the Oracle Toplink stuff but the complete Bea/Eclipse Suite is a lot better and easier to use.