在花了许多时间在网上搜索之后,尝试找到对几个项目使用Spring,JPA和Hibenate的最有效方法,我们得出了将在下面介绍的配置的结论。 将Spring与JPA和Hibernate集成包括几个步骤:
- Spring容器的配置
- JPA ORM层的配置
- Hibernate Second lvl缓存的配置(如果需要)
请记住,就数据源而言,我们假设我们在J2EE容器内进行操作,因此我们将要从JNDI查找现有数据源并使用它。 我们将要配置的文件如下所述:
- spring.xml文件,用于驱动spring容器。
- 驱动JPA ORM层的persistence.xml文件
- 第二个lvl缓存文件,例如JBoss TreeCache提供程序的treecache.xml (如果需要)
下面是一个示例spring.xml文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"
>
<context:component-scan base-package="com.mycomp.mypackage" />
<task:annotation-driven executor="myExecutor" scheduler="myScheduler" />
<task:executor id="myExecutor" pool-size="5" />
<task:scheduler id="myScheduler" pool-size="10" />
<tx:annotation-driven />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="MyPersistenceUnit" />
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager" />
<property name="userTransactionName" value="UserTransaction" />
</bean>
</beans>
这里需要注意的几件事
- 将context:component-scan标签的base-package属性更改为项目的基本包,以便对其进行Spring组件(服务,DAO等)的扫描。
- 根据persistence.xml文件中的指示,将entityManagerFactory bean的persistentUnitName属性的value属性更改为您的持久单元的名称
下面显示了一个示例persistence.xml文件:
<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="MyPersistenceUnit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MyDataSource</jta-data-source>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<!-- Uncomment below to use Hibernate second lvl cache -->
<!--
<property name="hibernate.cache.provider_class"
value="org.hibernate.cache.TreeCacheProvider"/>
<property name="hibernate.treecache.mbean.object_name"
value="jboss.cache:service=TreeCache"/>
<property name="hibernate.cache.use_second_level_cache"
value="true"/>
<property name="hibernate.cache.use_query_cache"
value="true"/>
<property name="hibernate.cache.use_structured_entries"
value="true"/>
-->
</properties>
</persistence-unit>
</persistence>
这里需要注意的几件事:
- 持久性单元名称(此处为MyPersistenceUnit)必须与spring.xml文件中的值匹配
- 事务类型可以具有JTA或LOCAL值,我们的假设是我们正在启用JTA的容器中进行部署,因此我们可以利用全局事务(JTA),在任何其他情况下,都应使用LOCAL值
- 如上所述,我们假设我们正在J2EE容器中进行部署,并且数据源在单独的文件中声明并且位于JNDI中,因此我们指示JPA使用在特定JNDI名称下找到的数据源,您应该根据您的数据源JNDI名称
- 我们要求休眠状态使用Hypersonic方言,您应该根据数据源更改此值,例如,对于MySQL,此值应为org.hibernate.dialect.MySQLDialect(用于myISAM引擎)或org.hibernate.dialect.MySQLInnoDBDialect(用于InnoDB引擎)
- 我们要求休眠状态来查找我们的JTA事务管理器,例如,如果我们在JBoss内部部署,则使用指定的值,您应该根据您的环境更改此值
- 如果要启用Hibernate第二个lvl缓存,只需取消注释指定的配置指令
下面显示了一个示例第二个lvl缓存(JBoss树缓存– treecache.xml)文件:
<server>
<classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar" />
<mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">
<depends>jboss:service=Naming</depends>
<depends>jboss:service=TransactionManager</depends>
<attribute name="TransactionManagerLookupClass">
org.jboss.cache.JBossTransactionManagerLookup</attribute>
<attribute name="IsolationLevel">REPEATABLE_READ</attribute>
<attribute name="CacheMode">LOCAL</attribute>
<attribute name="UseReplQueue">false</attribute>
<attribute name="ReplQueueInterval">0</attribute>
<attribute name="ReplQueueMaxElements">0</attribute>
<attribute name="ClusterName">TreeCache-Cluster</attribute>
<attribute name="ClusterConfig">
<config>
<UDP mcast_addr="228.1.2.3" mcast_port="48866" ip_ttl="64"
ip_mcast="true" mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
ucast_send_buf_size="150000" ucast_recv_buf_size="80000" loopback="false" />
<PING timeout="2000" num_initial_members="3" up_thread="false"
down_thread="false" />
<MERGE2 min_interval="10000" max_interval="20000" />
<FD_SOCK />
<VERIFY_SUSPECT timeout="1500" up_thread="false"
down_thread="false" />
<pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
max_xmit_size="8192" up_thread="false" down_thread="false" />
<UNICAST timeout="600,1200,2400" window_size="100"
min_threshold="10" down_thread="false" />
<pbcast.STABLE desired_avg_gossip="20000" up_thread="false"
down_thread="false" />
<FRAG frag_size="8192" down_thread="false" up_thread="false" />
<pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
shun="true" print_local_addr="true" />
<pbcast.STATE_TRANSFER up_thread="true"
down_thread="true" />
</config>
</attribute>
<attribute name="FetchInMemoryState">true</attribute>
<attribute name="InitialStateRetrievalTimeout">20000</attribute>
<attribute name="SyncReplTimeout">20000</attribute>
<attribute name="LockAcquisitionTimeout">15000</attribute>
<attribute name="EvictionPolicyClass"></attribute>
<attribute name="UseMarshalling">false</attribute>
</mbean>
</server>
这里需要注意的几件事
- 更新类加载器的路径,以找到两个必需的文件(jboss-cache.jar,jgroups.jar),JBoss树缓存才能正常工作
- 该文件将树缓存配置为JBoss MBean服务,因此必须将其部署在JBoss应用服务器中,其他配置类型不在本教程的讨论范围之内,因此将不作进一步讨论。 有关在其他环境中配置JBoss树缓存的信息,请参考相应的文档。
就是这样,现在让我根据上述配置介绍一个示例DTO和DAO:
首先是DTO类(EmployeeDTO)
package com.mycomp.myproject.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "EMPLOYEE")
public class EmployeeDTO implements java.io.Serializable {
private static final long serialVersionUID = 7440297955003302414L;
@Id
@Column(name="employee_id")
private long employeeId;
@Column(name="employee_name", nullable = false, length=30)
private String employeeName;
@Column(name="employee_surname", nullable = false, length=30)
private String employeeSurname;
@Column(name="job", length=50)
private String job;
public EmployeeDTO() {
}
public EmployeeDTO(int employeeId) {
this.employeeId = employeeId;
}
public EmployeeDTO(long employeeId, String employeeName, String employeeSurname,
String job) {
this.employeeId = employeeId;
this.employeeName = employeeName;
this.employeeSurname = employeeSurname;
this.job = job;
}
public long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(long employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEmployeeSurname() {
return employeeSurname;
}
public void setEmployeeSurname(String employeeSurname) {
this.employeeSurname = employeeSurname;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
}
以下是用于访问员工数据的DAO类(EmployeeDTO)
package com.mycomp.myproject.dao;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.mycomp.myproject.dto.EmployeeDTO;
@Repository("employeeDAO")
public class EmployeeDAO extends JpaDAO<Long, EmployeeDTO> {
@Autowired
EntityManagerFactory entityManagerFactory;
@PostConstruct
public void init() {
super.setEntityManagerFactory(entityManagerFactory);
}
}
如您所见,EmployeeDAO类扩展了基本的DAO类(JpaDao)。 EmployeeDAO类可以包含有关EmployeeDTO对象的特定查询,但是所有CRUD操作都可以从下面提供的基本DAO类(JpaDao)中进行处理:
package com.mycomp.myproject.dao;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.support.JpaDaoSupport;
public abstract class JpaDAO<K, E> extends JpaDaoSupport {
protected Class<E> entityClass;
@SuppressWarnings("unchecked")
public JpaDAO() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass()
.getGenericSuperclass();
this.entityClass = (Class<E>) genericSuperclass
.getActualTypeArguments()[1];
}
public void persist(E entity) {
getJpaTemplate().persist(entity);
}
public void remove(E entity) {
getJpaTemplate().remove(entity);
}
public E merge(E entity) {
return getJpaTemplate().merge(entity);
}
public void refresh(E entity) {
getJpaTemplate().refresh(entity);
}
public E findById(K id) {
return getJpaTemplate().find(entityClass, id);
}
public E flush(E entity) {
getJpaTemplate().flush();
return entity;
}
@SuppressWarnings("unchecked")
public List<E> findAll() {
Object res = getJpaTemplate().execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query q = em.createQuery("SELECT h FROM " +
entityClass.getName() + " h");
return q.getResultList();
}
});
return (List<E>) res;
}
@SuppressWarnings("unchecked")
public Integer removeAll() {
return (Integer) getJpaTemplate().execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query q = em.createQuery("DELETE FROM " +
entityClass.getName() + " h");
return q.executeUpdate();
}
});
}
}
本教程的第二部分总结了我们将在此处讨论有关Spring服务创建的内容。
贾斯汀
翻译自: https://www.javacodegeeks.com/2010/05/jboss-42x-spring-3-jpa-hibernate.html