This page (revision-12) was last changed on 18-Aug-2014 15:03 by Dieter Käppel

This page was created on 13-Dec-2010 16:31 by Dieter Käppel

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Page revision history

Version Date Modified Size Author Changes ... Change note
12 18-Aug-2014 15:03 7 KB Dieter Käppel to previous
11 18-Aug-2014 15:03 5 KB Dieter Käppel to previous | to last
10 04-Jul-2014 13:19 4 KB Dieter Käppel to previous | to last
9 29-Dec-2012 13:07 3 KB Dieter Käppel to previous | to last
8 30-Nov-2012 13:40 5 KB Dieter Käppel to previous | to last
7 24-Nov-2012 11:54 5 KB Dieter Käppel to previous | to last
6 23-Nov-2012 21:02 4 KB Dieter Käppel to previous | to last
5 23-Nov-2012 08:12 4 KB Dieter Käppel to previous | to last
4 01-Nov-2012 23:48 3 KB Dieter Käppel to previous | to last
3 15-Dec-2010 13:23 1 KB Dieter Käppel to previous | to last
2 15-Dec-2010 11:00 1 KB Dieter Käppel to previous | to last
1 13-Dec-2010 16:31 300 bytes Dieter Käppel to last

Page References

Incoming links Outgoing links

Version management

Difference between version and

At line 36 changed 3 lines
!!Local Container Manager vs. Local Entity Manager
Neben dem LocalContainerEntityManagerFactoryBean gibt es noch den LocalEntityManagerFactoryBean, der einfacher zu konfigurieren und zunächst ohne Container, das heißt JNDI auskommt:
!!!Spring Open EntityManager once in View Pattern
web.xml:
At line 40 changed 14 lines
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" lazy-init="true">
<property name="persistenceUnitName" value="subflowDb"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.connection.url">jdbc:hsqldb:file:${project.build.directory}/hsql/data</prop>
<prop key="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.connection.username">sa</prop>
<prop key="hibernate.connection.password"></prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<filter>
<filter-name>EntityManagerFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EntityManagerFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
At line 56 changed 2 lines
Allerdings ist es auch möglich, den LocalContainerEntityManagerFactoryBean lokal zu konfigurieren, sodass er z.B. aus einem JUnit-Test mit Spring heraus läuft:
!!!Spring Open EntityManager in Session
Nicht getestet ob das praktikabel ist.
At line 59 changed 20 lines
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager">
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations" value="classpath*:META-INF/persistence.xml"/>
<property name="defaultDataSource" ref="dataSource"/>
</bean>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="16000"/>
<property name="minIdle" value="0"/>
</bean>
}}}
public class OpenEntityManagerInSessionFilter extends OncePerRequestFilter {
public static final String ENTITY_MANAGER_FACTORY_NAME = "entityManagerFactory";
public static final String ENTITY_MANAGER_NAME = "entityManager";
At line 80 changed one line
Der Test sieht dann so aus:
private String entityManagerFactoryBeanName = ENTITY_MANAGER_FACTORY_NAME;
At line 82 changed 10 lines
{{{
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/testApplicationContext.xml")
// @TransactionConfiguration(defaultRollback = false)
public class SpringDBTest {
@Test
@Transactional
public void test() {
Criteria criteria = ((Session)entityManager.getDelegate()).createCriteria(Test.class);
...
public void setEntityManagerFactoryBeanName(String entityManagerFactoryBeanName) {
this.entityManagerFactoryBeanName = entityManagerFactoryBeanName;
At line 93 removed 2 lines
}
}}}
At line 96 changed 2 lines
!!!Lazy-Loading und Transaction Management
Es ist praktikabel, das JPA Transaction Management zusammen mit Spring zu verwenden (Annotation <tx:annotation-driven/>). Für die View kann dann der OpenEntityManagerInViewFilter verwendet werden, um Paging und Lazy-Loading zu realisieren:
public String getEntityManagerFactoryBeanName() {
return entityManagerFactoryBeanName;
}
At line 99 changed 10 lines
{{{
<filter>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
}}}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
EntityManagerFactory entityManagerFactory = lookupEntityManagerFactory();
boolean participate = false;
try {
if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) {
participate = true;
} else {
EntityManager entityManager = (EntityManager)request.getSession().getAttribute(ENTITY_MANAGER_NAME);
if (entityManager == null) {
entityManager = entityManagerFactory.createEntityManager();
request.getSession().setAttribute(ENTITY_MANAGER_NAME, entityManager);
}
TransactionSynchronizationManager.bindResource(
entityManagerFactory, new EntityManagerHolder(entityManager));
}
filterChain.doFilter(request, response);
} finally {
if (!participate)
TransactionSynchronizationManager.unbindResource(entityManagerFactory);
}
}
At line 110 changed 4 lines
Der EntityManager kann allerdings die Session nur öffnen, wenn der Hibernate-Parameter dafür gesetzt ist (etwa in der persistence.xml):
{{{
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
protected EntityManagerFactory lookupEntityManagerFactory() {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
return (EntityManagerFactory) wac.getBean(getEntityManagerFactoryBeanName(), EntityManagerFactory.class);
}
}
At line 117 changed one line
In Hibernate sind die Criteria Querys eins der mächstigsten Instrumente, da sie rein durch ein Programm erzeugt werden können.
In Hibernate sind die Criteria Querys eine der mächstigsten Instrumente, da sie rein durch ein Programm erzeugt werden können.
At line 132 removed 14 lines
!!Unabhängige Subquery
Subquerys können nur verwendet werden, wenn statt Restrictions über Property.forName(...) gegangen wird:
{{{
Criteria criteria = session.createCriteria(Transition.class);
DetachedCriteria subquery = DetachedCriteria.forClass(Participant.class);
subquery.add(Restrictions.eq("user", user));
subquery.setProjection(Projections.property("role"));
criteria.add(Property.forName("actor").in(subquery));
}}}
!!Abhängige Subquery
Wenn Subquerys über Properties mit der Hauptquery verbunden sind, geht das nur über Aliase. Diese können beim erzeugen von Criterias und Subcriterias angegeben werden, sowie für Properties festgelegt.
At line 158 removed 27 lines
!!!Database Connections
Hibernate bringt zwar ein Connection Management in der Default Configuration mit, das ist allerdings nicht besonders ausgereift. Inzwischen in das Hibernate Projekt integriert ist das C3P0-Connection Management:
{{{
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
</dependency>
}}}
Der wichtigste Parameter besteht darin, in der persistence.xml das Connection-Verifying zu aktivieren:
{{{
<property name="hibernate.c3p0.testConnectionOnCheckout" value="true"/>
}}}
!!!Collections
Ein Vorteil bei Einsatz ist [Hibernate] das Handling von Collections, also 1:n Beziehungen. Allerdings entsteht dadurch die eine oder andere Verwicklung.
!!Mergen von DAGs
Beim Mergen reiner Baumstrukturen arbeitet Hibernate 4 inzwischen recht zuverlässig. Werden allerdings Directed Acyclic Graphs (DAGs) gespeichert, kommt es beim Mergen zu Fehlern. Dies kann durch [JPA Fix] beseitigt werden.
!!Delete before Insert
In der Klasse org.hibernate.engine.internal.Cascade, Methode cascadeCollectionElements ist fest verankert, dass Orphan-Delete nach dem Insert ausgeführt wird. Bei Unique-Constrains kann dies zu Konflikten führen, da der Delete noch nicht ausgeführt wird.
In Oracle kann dies gelöst werden, indem dem Unique Key ein DEFERRABLE INITIALLY DEFERRED hinzugefügt wird. Dies führt dazu, dass der Unique Key erst beim Commit geprüft wird. Zu diesem Zeitpunkt ist die vorübergehende Inkonsistenz der Daten wieder beseitigt.