SakaiPersistenceAndHibernate

Download Report

Transcript SakaiPersistenceAndHibernate

Sakai Persistence
and
Hibernate
Aaron Zeckoski
[email protected]
Creative Commons AttributionNonCommercial-ShareAlike 2.5 License
Sakai Programmer's Café
How do we persist data in Sakai?
• Sakai has a single central database configured
– Virtually every tool/component uses this
• Sakai in production is typically a clustered
environment, and the clustering implementation
is largely based around the database
– Tools that will not cluster are very unlikely to be
adopted into the core
• You should use the database in pretty much
every case
– File system storage can be appropriate for “bulky”
resources (Files or Blobs) so data is accessible via
WebDav
2
Databases and Sakai
• Settings to control the database that is
used are stored in sakai.properties
– This is a standard format Java .properties file
• The sakai.properties file is located in your
sakai home in the subdirectory named
sakai
– this is configurable but is normally your
Tomcat home
• Look for the following line in the file
# DATABASE CONFIGURATION
3
Supported databases
•
Only 4 databases are supported for use in
Sakai
1. HSQLDB
–
*very* lightweight, pure-Java database, largely for testing
and developing, storage either in memory or a flat text file
2. MySQL
–
Open source, pretty good performance, used widely in
production, some very unfortunate locking issues
3. Oracle
–
Costs money, high performance, pretty rock solid, works
well for those that can/are prepared to afford it
4. DB2
–
•
Costs money, trunk only, similar pros/cons to Oracle
Since the majority of Sakai code uses raw SQL
in some form, adding a new database is a
major effort (e.g. DB2, MSSQL)
4
Some DB config tips
• Always leave auto.ddl=true
– You might want to turn this off for production
environments
• HSQLDB is turned on by default, it only
stores data in memory by default
• HSQLDB works well for development and
for demos
– Caveat: You cannot look at the HSQLDB
database without some serious trickery
5
More DB config tips
• MySQL despite being a “production” option
is actually really easy to set up for
development
– Allows you to look at the database through its
console to see if things are working
– Works well on most platforms and tends to get
into a lock state somewhat easily which helps
you find transaction problems
• If all else fails, switch to HSQLDB file
storage
6
HSQLDB file storage
• To use HSQLDB in file mode (where it
stores data on the filesystem), comment
out this line:
[email protected]=jdbc:hsqldb:.
• and uncomment this one
[email protected]=
jdbc:hsqldb:${sakai.home}/db/sakai.db
7
MySQL config
• To use MySQL, uncomment the six lines
under this line: ## MySQL settings
• Comment out the 7 lines under this one:
## HSQLDB settings
• Update the username and password lines
to match your MySQL database
8
One last DB tip
• You can turn on verbose Hibernate logging
in the sakai.properties file
• Change the following from false to true
# enable hibernate SQL debugging output
hibernate.show_sql=false
– Note: You do NOT want to leave this on in a
production environment
9
3 ways to persist data to the DB
JDBC
http://java.sun.com/products/jdbc/
Spring JDBC
http://www.springframework.org/docs/refere
nce/jdbc.html
Hibernate
http://www.hibernate.org/
10
Persistence rundown
• Java Database Connectivity
– Don’t use this alone!
• Spring JDBC
– If you are good with SQL, this is for you
• Hibernate
– Use this for fastest initial development
– Some caveats
URL: http://bugs.sakaiproject.org/confluence/display/BOOT/Persistence
11
Hibernate Commentary
• Beyond the hype:
– Hibernate *is* the most popular full ORM persistence framework
• probably in any language
– Not to say it is without numerous issues
• ORM is a tricky problem and general solutions are very difficult
– Many aspects of the Hibernate framework are “over-eager”
• lazy Collections, cascade options, long transactions
– Many aspects of Hibernate are overly rigid
• proxy behaviour, initial configuration sets cannot be changed, poor
cross-ClassLoader behaviour
• Advice
– Use it cautiously! (pay attention to tips)
– Avoid lazy Collections, be conservative with cascade options
– In general just use it on one entity at a time, with explicit
save/load on for each database operation
– In some cases you may still actually want to fall back to SQL
• recommended by the Hibernate team for certain situations
12
Hibernate Tips Avoid primitives
• Don’t use primitives for properties on
persistent objects
– This works fine in general but it does not
work if you are doing a findByExample
• If you do decide to use primitives, you cannot
leave them null/unset when doing a
findByExample or they will be set to the default
value for that primitive
– Things seem to work better when not using
primitives sometimes (e.g. Boolean)
13
Hibernate Tips don’t preset values
• Don’t set the values of persistent
objects in the POJO
– This can cause problems with frameworks
that expect to be able to instantiate the
POJO with all properties unset
– It may be more work to set the properties
for all non-null attributes but it is worth it
14
Hibernate Tips save dependent objects first
• If you have any dependent entities as
properties of a persistent object you
*must* save them before saving the
parent class
– Hibernate has numerous “cascade” options
that claim to do this automatically, but it is
best to start simple
– The same thing goes for deleting
15
Hibernate Tips non-primitive generated ids
• Use non-primitive generated ids for the
primary key of persistent objects
– It is more efficient and is a good idea in
most databases anyway
• This kind of primary key is recommended
– Use java.lang.Long or java.lang.String for
best results
• More best practices here:
http://www.hibernate.org/hib_docs/reference/en/html/best-practices.html
16
Hibernate in Sakai
•
3 ways of using Hibernate in Sakai
1. Create a SessionFactory using settings inside
your tool
2. Create a SessionFactory from the global Sakai
SessionFactoryBase
3. Add our HBMs to the global Sakai
SessionFactory
•
Sakai 2.2+ uses Hibernate 3

Previous versions used Hibernate 2
From: http://bugs.sakaiproject.org/confluence/display/BOOT/Hibernate+in+Sakai
17
Method 1
• Create a Hibernate SessionFactory
using config settings in your tool
– You should use this when connecting to an
external database
– Do not use this method to connect to the
internal Sakai database!
– More info on session configuration:
http://www.hibernate.org/hib_docs/reference/en/html/session-configuration.html
18
Method 2
• Create a SessionFactory from the
global Sakai SessionFactoryBase
– This is not the recommended method but if
you are creating a webapp only project for
your app then you have to use it
• This method works OK for simple tools
– Demonstrated in tasklist-simple
– More complex tools should use method 3
From: http://bugs.sakaiproject.org/confluence/display/BOOT/Creating+sessions+from+the+Sakai+SessionFactoryBase
19
Method 3
• Add our HBMs to the global Sakai
SessionFactory using
AddableSessionFactoryBean
– This is the preferred method
– Works best for all but the simplest apps
– Requires the tool to deploy portions to
shared and components so it requires more
complexity
• Demonstrated in tasklist
URL: http://bugs.sakaiproject.org/confluence/display/BOOT/Using+the+Sakai+global+sessionFactory
20
Use the Generic Dao package
• The GenericDao is an abstraction layer that
will allow you to use Hibernate/JDBC with
your persistent objects without needing to
write a DAO at all
• It has usage information in the Javadocs
• Highly configurable and extendable
• Has no Hibernate/JDBC dependencies in the
interfaces (*any* DAO should be like this)
URL: http://bugs.sakaiproject.org/confluence/display/BOOT/Generic+DAO+package 21
More on GenericDao
• Get the code and Javadocs from the Sakai
Maven repository:
– http://bugs.sakaiproject.org/confluence/display/BOOT/Generic+DAO+package
• Usage is demonstrated in BlogWow,
Evaluation, QnA, and other Sakai apps:
– https://source.sakaiproject.org/contrib/
• Also used in the app builder plugin
• Used in production apps
• Many internal unit tests and usage outside Sakai
22
Look at some sample code
• Look at the tasklist code here if you like:
– https://source.sakaiproject.org/contrib/tasklist/trunk/
• You could also use the Sakai app builder
tool in Eclipse to create a simple CRUD
app to follow along
• Let’s see what it takes to use Hibernate in
Sakai…
23
Update impl maven config
• Add the Hibernate dependency to the
maven POM.xml file
• Note that we use dependency
management from master POM
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
</dependency>
24
Hibernate Mapping Files
• Hibernate uses an XML file to map Java
objects onto database columns
• We will create our mapping file from a
simple template attached to the
persistence page
• For applications with many tables, use a
tool to help generate the HBM files
25
Package for the HBM
• Create a new Java package for the
HBM (mapping file)
– org.sakaiproject.toolname.impl.hbm
• Create a new file in this package
– MyObject.hbm.xml
• This file must end up in shared
26
Basic HBM template
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.sakaiproject.toolname.model.MyObject "
table="TOOLNAME_MYOBJECT">
<id name="id" type="long">
<generator class="native">
<param name="sequence">MYOBJECT_ID_SEQ</param>
</generator>
</id>
<property name="myProperty" type="string"
length="255" not-null="true”/>
</class>
</hibernate-mapping>
27
Template customization
• Change the class name and table name
– org.sakaiproject.toolname.model.MyObject
• Change the id sequence name
• Copy and paste the property block to add the
properties from your persistent object
– owner
– siteId
– creationDate
• Etc…
28
Creating a DAO for Hibernate
• Create a new class which implements
your DAO interface
– Write a DAO interface if you do not have one
• Extend HibernateDaoSupport
– part of Spring-Hibernate
• Add import for HibernateDaoSupport
– Make sure you use the one for hibernate 3
• Or use Generic DAO package!
29
Spring configuration
• Now we need to tie everything together
with Spring
• First we will tell hibernate about our
MYObject.hbm.xml mapping file
• Next we will give the hibernate stuff to
our DAO implementation
• Finally we will tie the new DAO to the
rest of the webapp
30
Adding our HBMs to the Sakai
Global SessionFactory
<bean id="org.sakaiproject.yourapp.hibernate.
AdditionalHibernateMappings"
class="org.sakaiproject.springframework.orm.hibernate.
impl.AdditionalHibernateMappingsImpl">
<property name="mappingResources">
<list>
<value>
org/sakaiproject/yourapp/impl/hbm/Item1.hbm.xml
</value>
</list>
</property>
</bean>
• This allows us to use our persistent objects
with the Sakai Global SessionFactory
31
Inject the Global
SessionFactory into the DAO
<bean id="org.sakaiproject.yourapp.dao.MyToolDaoTarget"
class="org.sakaiproject.yourapp.dao.impl.MyToolDaoImpl">
<property name="sessionFactory">
<ref bean="org.sakaiproject.springframework.orm.
hibernate.GlobalSessionFactory" />
</property>
</bean>
• This connects the new DAO to global Sakai
Hibernate
• The DAO implementation should extend
HibernateDaoSupport
32
Define a declarative
transaction interceptor
<bean id="org.sakaiproject.yourapp.dao.MyToolDao”
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean=
"org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager" />
</property>
<property name="target">
<ref bean="org.sakaiproject.yourapp.dao.MyToolDaoTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
• If your operations are not in a transaction you will see
many problems, especially in MySQL
• This involves much less work than opening and
closing transactions in code, and is more reliable
33
Good to go!
• You should be able to start up your app
and happily access any database!
• Hibernate will create or update tables as
needed
34
Any questions?
• Check out the section on persistence
in the Programmers’ Café for more
information
http://bugs.sakaiproject.org/confluence/display/BOOT/Persistence
• Hibernate: http://www.hibernate.org/
• Spring ORM
http://www.springframework.org/docs/reference/orm.html
35