first blog entry and immediately brings heavy guns - the management of transactions in the environment bazodanowymi Spring + Hibernate. Theoretically, the matter is very simple - Spring, by HibernateDaoSupport, provides a whole set of methods for painless use of the data (add, delete) without bothering sessions, transactions, flushowaniem, commitowaniem, etc. Such an improvement may seem very attractive, but in certain situations (read: usually) creates a lot of problems.
Below I will try to describe how to tame and control the sessions of the transactions while working with springowym HibernateDaoSupport.
Pozwoję omit the details of an implementation, focusing only on the merits.
classic example: we have a product class and the class B category. One product can be only one category, the category has a set of products, and therefore the relationship between "one to many".
Klasy POJO i mapowania:
<class name="Kategoria" table="kategoria">
<id name="id" unsaved-value="null" column="kategory_id">
<generator class="sequence">
<param name="sequence">kat_seq</param>
</generator>
</id>
<property name="name"/>
<property name="type"/>
<property name="description"/>
\u0026lt;set name="products" lazy="true">
\u0026lt;key column="kategory_id"/>
\u0026lt;one-to-many class="Produkt"/>
\u0026lt;/ set>
\u0026lt;/ class>
\u0026lt;class name="Produkt" table="produkt">
\u0026lt;id name="id" unsaved-value="null" column="produkt_id">
\u0026lt;generator class = "sequence">
\u0026lt;param name="sequence"> prod_seq \u0026lt;/ param>
\u0026lt;/ generator>
\u0026lt;/ id> \u0026lt;property
name="name"/>
\u0026lt;property name="value"/>
\u0026lt;many-to-one name="kategoria" class="Kategoria"/> ;
\u0026lt;/ class>
General for all the DAO objects:
GenericDao public class extends HibernateDaoSupport
{public void store (Object object) {
getHibernateTemplate (). saveOrUpdate (object) ;
};
public void delete (Object object) {
getHibernateTemplate (.) delete (object);
};
\u0026lt;OBJECT> public List find (String query) {return
getHibernateTemplate (). Find (query);}
findUnique public Object (String query) {List \u0026lt;OBJECT>
getHibernateTemplate list = () . find (query);
if (list.size ()> 0) return
list.get (0);
else return null;}
}
assume that all the DAO will support the editing inherit from this class :
public class KategoriaDao extends GenericDao {
public Kategoria findKategoriaByName(String name) {
return (Kategoria)findUnique("... where name = "+name);
}
}
public class ProduktDao extends GenericDao {
public Produkt findProduktByName(String name) {
return (Produkt)findUnique("... where name = "+name);
}
}
Teraz praktyczne działanie:
public void testInsert() {
Kategoria kat = new Kategoria();
kat.setName("kat");
kat.setDescription("desc");
kategoriaDao.store(kat);
}
Po wywolaniu metody store() obiekt kat zostal zapisany in the database. Without creating a session, approve the transaction, bring coherence to the database with objects ...
Simply - calling one method and category in the database. Simple, right?
Assume that the database is a category called "cat". The database, there are four products in this category.
testSelect public void () {Category cat =
kategoriaDao.findKategoriaByName ("cat");
System.out.println (kat.getName ()) / / kat
System.out.println (kat.getDescription ( )) / / desc
}
Hmm ... even simpler matter. Write to the database by one method (store) I read it one (find. ..), nowhere in the code does not appear
magic word "session", HibernateDaoSupport is sensational!
Ok, but before we determine that a company with Spring Hibernate will do everything for us, let's look at kojeny example
testSelectCollections public void () {Category cat =
kategoriaDao.findKategoriaByName ("cat");
for (Product p: kat.getProducts ()) {System.out.println
(p.getName ());}
}
In operation method will thrown an exception LazyInitializationException: no session or session was closed.
Hmm ... first once there is so little word "session". What happened?
category has a set of products, which is initialized as "lazy" (
category in the database will NOT be downloaded products in the category. Products will be pulled from the database only when needed
(will appeal to them). Such an appeal shall be in the loop in the method testSelectCollections (). So why
products will not be taken at this time? As the session ended with the database and the connection is inactive. But how know where it begins and where it ends and how
session control it? Well, self-managed sessions Spring opening them only for the duration of the HibernateDaoSupport method call. To be precise:
testSelectCollections public void () {
/ / there is no session
Category cat = kategoriaDao.findKategoriaByName ("cat") / / session is
/ / there is no session
for (Product p: kat.getProducts ()) {System.out.println
(p.getName ());}
}
Fortunately, Spring allows you to control the session. With the help comes Aspect Oriented Programming (AOP) that (using such phrases) indicates Springowi
where it begins and where it ends the transaction, and hence and the session. Using @ Transactional annotation to mark a method that is to be done in one transaction:
@ Transactional public void
testSelectCollections () {Category cat =
kategoriaDao.findKategoriaByName ("cat");
for (Product p: kat.getProducts ()) {System.out.println
(p.getName ());}
}
session lasts throughout the time of the method. There is only one condition - @ Transactional annotations only work in classrooms that are beanami springowymi!
Problem solved!
To everything worked, you need to tell Spring to make arrangements with annotations and AOP. Here's an example configuration file:
\u0026lt;? Xml version = "1.0" encoding = "UTF-8"?>
\u0026lt;beans xmlns = "http://www.springframework.org/schema/beans"
xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns: context = "http://www.springframework.org/schema/context"
xmlns: tx = "http:/ / www.springframework.org / schema / tx "
xmlns: aop =" http://www.springframework.org/schema/aop "
xsi: schemaLocation ="
http://www.springframework.org/schema/beans
classpath:org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
classpath:org/springframework/transaction/config/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
classpath:org/springframework/aop/config/spring-aop-2.0.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
...
</bean>
<bean id="localSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
...
</list>
</property>
<property name="hibernateProperties">
<ref bean="hibernateProperties" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
\u0026lt;property name="sessionFactory" ref="localSessionFactory" />
\u0026lt;/ bean>
\u0026lt;tx:annotation-driven/>
\u0026lt;/ beans>
file with all the most important are:
- \u0026lt;tx:annotation-driven> - literally "controlled transactions annotations"
- correct schemaLocation
It should also be noted that the spring attached to the project wanted to work together. Once upon a time I could not come to grips with AOP
needed because each jar was from another parish. " Thorough cleanup pom'ie were necessary. The following excerpt
according to pom'a that define the correct configuration jar'ów (\u0026lt;springframework.version> 2.0.6 \u0026lt;/ springframework.version>):
\u0026lt;dependencies>
\u0026lt;dependency>
\u0026lt; groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring \u0026lt;/ artifactId>
\u0026lt;version> springframework.version $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring-aspects \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version> ;
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring-aop \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring-beans \u0026lt;/ artifactId> ;
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring-context \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId> ;
\u0026lt;artifactId> spring-core \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring-dao \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency> ;
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId>-hibernate3 spring \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring-JMS \u0026lt;/ artifactId> ;
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId> spring-jmx \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId> ;
\u0026lt;artifactId> spring-remoting \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;dependency>
\u0026lt;groupId> org.springframework \u0026lt;/ groupId>
\u0026lt;artifactId>-webmvc spring \u0026lt;/ artifactId>
springframework.version \u0026lt;version> $ {} \u0026lt;/ version>
\u0026lt;/ dependency> ;
\u0026lt;dependency>
\u0026lt;groupId> net.sf.ehcache \u0026lt;/ groupId>
\u0026lt;artifactId> ehcache \u0026lt;/ artifactId>
\u0026lt;version> 1.5.0 \u0026lt;/ version>
\u0026lt;/ dependency>
\u0026lt;/ dependencies>
0 comments:
Post a Comment