下面我们加入JPA支持,并且将JPA和Spring集成起来。
(1).首先加入persistence.xml文件
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<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="JSJDemoPU"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>test.vo.Test</class>
<properties>
<!-- Hibernate 方言(只有Hibernate 才需要设置) -->
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect" />
<!-- Hibernate 显示调试 SQL -->
<property name="hibernate.show_sql" value="true" />
<!-- Hibernate 格式化sql -->
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
(2).之后建立一个值对象
代码如下:
package mangerTeam.vo;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* 运动员实体
*
* @author 刘岩
*/
@Entity
@Table(name = "player")
public class PlayersVO implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@Column(name = "name")
private String name;
@ManyToOne(optional=true, fetch = FetchType.LAZY)
@JoinColumn(name = "teamId")
private TeamVO teamVO;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable=false,name = "nationalityId")
private NationalityVO nationalityVO;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "pic")
private byte[] pic;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "mess")
private String mess;
@ManyToMany(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
@JoinTable(name = "plays_position", joinColumns = {@JoinColumn(name = "playerId") }, inverseJoinColumns = {@JoinColumn(name = "positionId") })
private Set<PositionVO> positions;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<PositionVO> getPositions() {
return positions;
}
public void setPositions(Set<PositionVO> positions) {
this.positions = positions;
}
public TeamVO getTeamVO() {
return teamVO;
}
public void setTeamVO(TeamVO teamVO) {
this.teamVO = teamVO;
}
public NationalityVO getNationalityVO() {
return nationalityVO;
}
public void setNationalityVO(NationalityVO nationalityVO) {
this.nationalityVO = nationalityVO;
}
public byte[] getPic() {
return pic;
}
public void setPic(byte[] pic) {
this.pic = pic;
}
public String getMess() {
return mess;
}
(3).之后写DAO
无论你是用IDE生成的DAO还是自己写的DAO,代码大致如下:
@Transactional
public class PlayerDAO extends JpaDaoSupport implements IPlayerDAO {
// property constants
public static final String NAME = "name";
public static final String MESS = "mess";
public static final String PIC = "pic";
public void save(PlayersVO entity) {
logger.info("saving Player instance");
try {
getJpaTemplate().persist(entity);
logger.info("save successful");
} catch (RuntimeException re) {
logger.error("save failed", re);
throw re;
}
}
public void delete(PlayersVO entity) {
logger.info("deleting Player instance");
try {
entity = getJpaTemplate().getReference(PlayersVO.class,
entity.getId());
getJpaTemplate().remove(entity);
logger.info("delete successful");
} catch (RuntimeException re) {
logger.error("delete failed", re);
throw re;
}
}
public PlayersVO update(PlayersVO entity) {
logger.info("updating Player instance");
try {
PlayersVO result = getJpaTemplate().merge(entity);
logger.info("update successful");
return result;
} catch (RuntimeException re) {
logger.error("update failed", re);
throw re;
}
}
public PlayersVO findById(Integer id) {
logger.info("finding Player instance with id: " + id);
try {
PlayersVO instance = getJpaTemplate().find(PlayersVO.class, id);
return instance;
} catch (RuntimeException re) {
logger.error("find failed", re);
throw re;
}
}
@SuppressWarnings("unchecked")
public List<PlayersVO> findByProperty(String propertyName,
final Object value, final int... rowStartIdxAndCount) {
logger.info("finding Player instance with property: " + propertyName
+ ", value: " + value);
try {
final String queryString = "select model from PlayersVO model where model."
+ propertyName + "= :propertyValue";
return getJpaTemplate().executeFind(new JpaCallback() {
public Object doInJpa(EntityManager em)
throws PersistenceException {
Query query = em.createQuery(queryString);
query.setParameter("propertyValue", value);
if (rowStartIdxAndCount != null
&& rowStartIdxAndCount.length > 0) {
// 有分页
int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
// 开始页
if (rowStartIdx > 0) {
query.setFirstResult(rowStartIdx);
}
// 一页最大记录数目
if (rowStartIdxAndCount.length > 1) {
int rowCount = Math.max(0, rowStartIdxAndCount[1]);
if (rowCount > 0) {
query.setMaxResults(rowCount);
}
}
}
return query.getResultList();
}
});
} catch (RuntimeException re) {
logger.error("find by property name failed", re);
throw re;
}
}
public List<PlayersVO> findByName(Object name, int... rowStartIdxAndCount) {
return findByProperty(NAME, name, rowStartIdxAndCount);
}
public List<PlayersVO> findByMess(Object mess, int... rowStartIdxAndCount) {
return findByProperty(MESS, mess, rowStartIdxAndCount);
}
public List<PlayersVO> findByPic(Object pic, int... rowStartIdxAndCount) {
return findByProperty(PIC, pic, rowStartIdxAndCount);
}
public List<PlayersVO> findAll(final int... rowStartIdxAndCount) {
logger.info("finding all Player instances");
try {
final String queryString = "select model from PlayersVO model";
return getJpaTemplate().executeFind(new JpaCallback() {
public Object doInJpa(EntityManager em)
throws PersistenceException {
Query query = em.createQuery(queryString);
if (rowStartIdxAndCount != null
&& rowStartIdxAndCount.length > 0) {
int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
if (rowStartIdx > 0) {
query.setFirstResult(rowStartIdx);
}
if (rowStartIdxAndCount.length > 1) {
int rowCount = Math.max(0, rowStartIdxAndCount[1]);
if (rowCount > 0) {
query.setMaxResults(rowCount);
}
}
}
return query.getResultList();
}
});
} catch (RuntimeException re) {
logger.error("find all failed", re);
throw re;
}
}
public static IPlayerDAO getFromApplicationContext(ApplicationContext ctx) {
return (IPlayerDAO) ctx.getBean("PlayerDAO");
}
}
(4).配置Spring文件applicationContext.xml
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
xmlns:tx="http://www.springframework.org/schema/tx" default-autowire="byName">
<!--数据源连接池,使用dbcp-->
<bean id="realPoolDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!--基本连接设值-->
<property name="driverClassName" value="org.gjt.mm.mysql.Driver" />
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/jsjdemo?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
<!--连接池参数设置-->
<property name="maxIdle" value="20" />
<property name="maxWait" value="1000" />
<property name="defaultAutoCommit" value="false" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="120" />
</bean>
<!-- c3p0连接池 -->
<bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="org.gjt.mm.mysql.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/jsjdemo?useUnicode=true&characterEncoding=UTF-8" />
<!-- 当连接池耗尽时候,一次获得连接数-->
<property name="acquireIncrement" value="5" />
<!-- 连接池最大数 -->
<property name="maxPoolSize" value="20" />
<!-- 连接池最小数-->
<property name="minPoolSize" value="5" />
<!-- 用户名-->
<property name="user" value="root" />
<!-- 用户密码-->
<property name="password" value="root"></property>
</bean>
<!--
类似于hibernate的SessionFactory,指定由spring容器Bean,即:LocalContainerEntityManagerFactoryBean
-->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="JSJDemoPU" />
<property name="dataSource" ref="c3p0DataSource" />
</bean>
<!--配置事务-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!--支持dao事务注解-->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Hibernate使用的SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!--数据源配置-->
<property name="dataSource">
<ref bean="c3p0DataSource" />
</property>
</bean>
<!--Spring注入Dao实现-->
<bean id="testDAO" class="test.dao.TestDAO">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="TeamDAO" class="mangerTeam.dao.TeamDAO">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="PositionDAO" class="mangerTeam.dao.PositionDAO">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="PlayerDAO" class="mangerTeam.dao.PlayerDAO">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="NationalityDAO" class="mangerTeam.dao.NationalityDAO">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
(5)修改faces-config.xml里面的内容
加入如下内容
<managed-bean>
<managed-bean-name>playersVO</managed-bean-name>
<managed-bean-class>
mangerTeam.vo.PlayersVO
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>playerAction</managed-bean-name>
<managed-bean-class>
mangerTeam.action.PlayerAction
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<!--从Spring得到的DAO-->
<managed-property>
<property-name>playerDAO</property-name>
<value>#{PlayerDAO}</value>
</managed-property>
<managed-property>
<property-name>playersVO</property-name>
<value>#{playersVO}</value>
</managed-property>
</managed-bean>
这样Spring的DAO就注入了该Action(我还是喜欢叫它Action),至于该Action的代码由于过长,就不在此列出,很简单。无非就是注入DAO,setter和getter呗。
到此JSF+Spring+JPA的环境算是集成起来了,项目代码结构图如下:
最后说一下JPA的缺点:
(1)必须使用在JDK1.5以上的环境,否则只能望JPA而兴叹。
(2)因为它是标准,还在不断的更新中,所以还是不太成熟,不敢保证之后会有很大的变动。
(3)和Hibernate一样,对于多个表(对象)的联合查询,效率比纯JDBC的执行sql要慢很多。
JSF的缺点:
(1)调试不是很方便。
(2)无论是sun的实现还是apache的实现,都存在比较多的bug。
(3)组件技术不如js开源框架灵活,有点鸡肋的感觉。