JSF+Spring+JPA(Hibernate实现)的环境搭建

写之前的感受

刘岩

       先说好的,文章后再说缺点。

JSF+Spring+JPA以我个人看来,应该说是Struts2+Spring+Hibernate的替代解决方案。

引入JPA去取代或者说包装或者说是升级Hibernate是为了符合JAVA EE的规范,达到ORM统一的结果。下次项目用EJB也好、用TOPLINK也好、用ibatis也罢,我们的开发人员代价会很小。在目前很多项目来说,引入此规范,能更好的代码复用,持久层和控制层相当于进一步的解耦合了,你只需要开启项目之前好好地建立领域模型。

那么用JSF取代Struts2或者更早一点的Struts1又是为何!答案依然是,它是规范。是符合某些标准的规范。不是说Struts2不好,这个因项目而定才行。我个人还是比较推崇apacheStruts2的,当然了,apacheJSF实现和JSF组件也是相当地杠杠的!!!!JSF更贴近事件比较多的web前端处理机制。想想我们一般要接收和处理页面的各种事件是用什么:js函数+ajax处理是吧(Flex我没有接触过,不知道它是怎么样的处理前后台交互的)。JSF可以采用事件监听机制,控件(JSF里面叫做控件)被触发了某些时间,直接优雅的和POJO进行了交互,配合ajax4jsf,处理大量的控件的事件是很简洁方便的。

言归正传,开始。。。

1.       首先利用IDE建立一个Web项目

2.       加入相应的jar包,注意:所有的开源框架都是加入jar包的时候最麻烦,尤其加入了Spring,搞不好就他妈的启动服务的时候报错。我已经将相应需要的jar包放到了csdn上面共享了,网址是http://download.csdn.net/source/2416493。大家可以去下载。

3.       web项目加入JSF支持

修改web.xml,加入如下内容

<!--SpringJSF支持-->

    <listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

 

    <!--配置JSF-->

    <context-param>

       <param-name>javax.faces.CONFIG_FILES</param-name>

       <param-value>/WEB-INF/faces-config.xml</param-value>

    </context-param>

 

    <!--Spring配置文件地址-->

    <context-param>

       <param-name>contextConfigLocation</param-name>

    <param-value>/WEB-INF/classes/applicationContext.xml</param-value>

</context-param>

<!--客户端管理状态-->

    <context-param>

       <param-name>javax.faces.STATE_SAVING_METHOD</param-name>

       <param-value>client</param-value>

    </context-param>

 

<!—加入facelets 框架支持-->

    <context-param>

       <param-name>facelets.LIBRARIES</param-name>

       <param-value>    /WEB-INF/facelets/tags/arcmind.taglib.xml;/WEB-INF/tomahawk.taglib.xml

       </param-value>

</context-param>

 

    <context-param>

       <description>指定facelets支持的后缀</description>

       <param-name>javax.faces.DEFAULT_SUFFIX</param-name>

       <param-value>.xhtml</param-value>

    </context-param>

 

    <!--JSFajax配置 AJAX4JSF-->

    <filter>

       <display-name>Ajax4jsf Filter</display-name>

       <filter-name>ajax4jsf</filter-name>

       <filter-class>org.ajax4jsf.Filter</filter-class>

    </filter>

    <filter-mapping>

       <filter-name>ajax4jsf</filter-name>

       <servlet-name>Faces Servlet</servlet-name>

       <dispatcher>REQUEST</dispatcher>

       <dispatcher>FORWARD</dispatcher>

       <dispatcher>INCLUDE</dispatcher>

</filter-mapping>

 

    <!—JSF支持-->

    <servlet>

       <servlet-name>Faces Servlet</servlet-name>

       <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

       <load-on-startup>1</load-on-startup>

    </servlet>

    <servlet-mapping>

       <servlet-name>Faces Servlet</servlet-name>

       <url-pattern>*.faces</url-pattern>

    </servlet-mapping>

 

<!—组件支持-->

    <filter>

       <description>为正确使用tomahawk组件包而配置</description>

       <filter-name>extensionsFilter</filter-name>

    <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>

       <init-param>

           <param-name>uploadMaxFileSize</param-name>

           <param-value>10m</param-value>

       </init-param>

       <init-param>

           <param-name>uploadThresholdSize</param-name>

           <param-value>100</param-value>

       </init-param>

    </filter>

 

    <filter-mapping>

       <filter-name>extensionsFilter</filter-name>

       <url-pattern>*.faces</url-pattern>

    </filter-mapping>

    <filter-mapping>

       <filter-name>extensionsFilter</filter-name>

       <url-pattern>/faces/*</url-pattern>

</filter-mapping>

 

WEB-INF下面加入jsf_core.tldhtml_basic.tldtomahawk.taglib.xml文件、新建一个faces-config.xml文件,内容配置如下:

<!--配置facelets-->

    <application>

       <locale-config>

           <default-locale>zh_CN</default-locale>

       </locale-config>      <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>

    </application>

 

<!—JSFSpring集成-->

    <application>

       <variable-resolver>

           org.springframework.web.jsf.DelegatingVariableResolver

    </variable-resolver>

    </application>

 

再加入facelets框架的标签支持包,整个环境包大致如下图所示:

 

4.       上面的配置好了,JSFSpring就集成起来了。下面我们加入JPA支持,并且将JPASpring集成起来。

首先加入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>

 

 

之后建立一个值对象,代码如下:

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;

    }

 

    public void setMess(String mess) {

       this.mess = mess;

    }

 

}

之后写DAO,无论你是用IDE生成的DAO还是自己写的DAO,代码大致如下:

package mangerTeam.dao;

 

import java.util.HashMap;

import java.util.List;

 

import javax.persistence.EntityManager;

import javax.persistence.PersistenceException;

import javax.persistence.Query;

 

import mangerTeam.vo.PlayersVO;

 

import org.springframework.context.ApplicationContext;

import org.springframework.orm.jpa.JpaCallback;

import org.springframework.orm.jpa.support.JpaDaoSupport;

import org.springframework.transaction.annotation.Transactional;

 

@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;

       }

    }

 

    /**

     * 按条件的复杂查询

     *

     * @param con

     * @param rowStartIdxAndCount

     * @return

     */

    @SuppressWarnings("unchecked")

    public List<PlayersVO> serch(final HashMap<String, Object> conMap,

           final String con, final int... rowStartIdxAndCount) {

 

       try {

           String queryString = "select model from PlayersVO model WHERE 1=1 ";

 

           if (con != null && !"".equalsIgnoreCase(con)) {

              queryString = queryString + con;

           }

 

           final String jpql = queryString;

 

           return getJpaTemplate().executeFind(new JpaCallback() {

              public Object doInJpa(EntityManager em)

                     throws PersistenceException {

 

                  Query query = em.createQuery(jpql);

 

                  for (int i = 0; i < conMap.size(); i++) {

                     String key = "option" + i;

                     query.setParameter(key, conMap.get(key));

                  }

 

                  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;

       }

 

    }

   

    /**

     * JPQL查询计算记录总数

     * @return

     */

    public Long countNumJPQL(){

       logger.info("finding all Team instances");

       try {

           final String queryString = "select COUNT(model) from PlayersVO model";

           return (Long)getJpaTemplate().executeFind(new JpaCallback() {

              public Object doInJpa(EntityManager em)

                     throws PersistenceException {

                  Query query = em.createQuery(queryString);

                 

                  return query.getResultList();

              }

           }).get(0);

       } catch (RuntimeException re) {

           logger.error("find all failed", re);

           throw re;

       }

    }

 

    public static IPlayerDAO getFromApplicationContext(ApplicationContext ctx) {

       return (IPlayerDAO) ctx.getBean("PlayerDAO");

    }

}

注意:之所以加入注解:@Transactional,是为了AOP进行事务处理。

配置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&amp;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&amp;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>

 

    <!--

       类似于hibernateSessionFactory,指定由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>

这样SpringDAO就注入了该Action(我还是喜欢叫它Action),至于该Action的代码由于过长,就不在此列出,很简单。无非就是注入DAOsettergetter呗。

到此JSF+Spring+JPA的环境算是集成起来了,项目代码结构图如下:

 

 

JPA的缺点:

必须使用在JDK1.5以上的环境,否则只能望JPA而兴叹。

因为它是标准,还在不断的更新中,所以还是不太成熟,不敢保证之后会有很大的变动。

Hibernate一样,对于多个表(对象)的联合查询,效率比纯JDBC的执行sql要慢很多。

JSF的缺点:

调试不是很方便。

无论是sun的实现还是apache的实现,都存在比较多的bug

组件技术不如js开源框架灵活,有点鸡肋的感觉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值