myeclipse2013下整合struts2、spring3、jpa2

      在myeclipse下,利用myeclipse自带的功能,为项目添加struts、jpa、spring的功能,可以极大的缩短开发时间。

     本文是利用struts为表现层,jpa为持久层,spring为业务层,利用spring的依赖注入管理struts的action和jpa的entityManager、jpa的事务管理。

     记录学习的脚步,!!!!!

1.在myeclipse下新建web project,名为SSJTest,并添加oracle 11g的驱动jar包,如下


2.为SSJTest项目添加spring功能,如下


点击install spring facet后,下一步如下


修改运行的目标环境后,其他的默认即可,一直点next,直至完成.

完成后 效果如下


打开web.xml文件中会发现 添加了如下配置信息

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

上面的ContextLoaderListener监听器用于初始化spring容器,此监听器会查找contextConfigLocation参数,然后获取其值作为spring容器的配置文件,如果不指定contextConfigLocation参数的话,则默认会查找/WEB-INF/applicationContext.xml 下面的配置文件

 3.给 SSJTest添加jpa功能,与添加sping功能很类似,并且利用myeclipse自带的jpa工程翻转,将oracle下面的stus表进行实体映射,并生成其数据访问层和数据访问层接口,

部分截图如下

jpa翻转


配置dao,并交由spring来进行管理


其他步骤,均下一步即可.最终效果


  此时为了spring为jpa管理其事务,还需在StusDao上加入@Transactional注解,以便于spring容器进行事务管理


      在添加struts功能之前,测试下spring与jpa的整合是否成功,于是添加junit test

  测试代码:

package com.undergrowth;

import static org.junit.Assert.*;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StusDAOTest {

	private static ApplicationContext ac;
	private static IStusDAO  isd;
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		//初始化spring容器
		ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		//获取stus的dao
		isd=(IStusDAO) ac.getBean("StusDAO");
		
	}

	@Test
	public void testSave() {
		Stus stus=new Stus(UUID.randomUUID().toString(), "马化腾", 45.0, Timestamp.valueOf(new Date().toLocaleString()));
		isd.save(stus);
	}

	@Test
	public void testDelete() {
		fail("Not yet implemented");
	}

	@Test
	public void testUpdate() {
		fail("Not yet implemented");
	}

	@Test
	public void testFindAll() {
		List<Stus> listStus=isd.findAll();
		for (Stus stus : listStus) {
			System.out.println(stus);
		}
	}

}

先运行testSave然后运行testFindAll,控制台输出

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[EL Info]: 2014-02-16 15:24:51.512--ServerSession(31211440)--EclipseLink, version: Eclipse Persistence Services - 2.4.2.v20130514-5956486
[EL Info]: connection: 2014-02-16 15:24:52.123--ServerSession(31211440)--file:/D:/learnsoftware/java/AndroidDevelop/myeclipse_2014_1_23/SSJTest/build/classes/_SSJTest login successful
Stus [stuId=b31494c8-1806-49b5-b490-49e8a57e38e3, stuName=马化腾, stuAge=45.0, stuBirthday=2014-02-16 15:24:34.0]

表明spring与jpa合成没有问题


4.为其添加struts功能,添加struts功能之后,在struts.xml配置文件中加入以下配置信息

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>

    <!-- 打开调试模式,获取更多的调试信息 -->
   <constant name="struts.devMode" value="true"></constant>
  <!--  使用spring容器来管理struts的action -->
	<constant name="struts.objectFactory" value="spring"></constant>
	
	
	<package name="stus" namespace="/stus" extends="struts-default">
	<!-- 使用*占位符来扩展多个方法 -->
		<action name="stus_*" class="stusAction" method="{1}">
			<result name="list">/WEB-INF/page/stusList.jsp</result>
		</action>
	</package>
</struts>    

spring的配置文件信息如下:

<?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-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
	xmlns:tx="http://www.springframework.org/schema/tx">

    
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="SSJTest" />
	</bean>
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	<!-- 用于jpa的事务管理 -->
	<tx:annotation-driven transaction-manager="transactionManager" />
	<bean
		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
	</bean>
	<bean
		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">
	</bean>
	<bean id="StusDAO" class="com.undergrowth.StusDAO"></bean>
	
	<bean id="stusAction" class="com.undergrowth.action.StusAction">
	<!-- 注入数据访问层 -->
		<property name="stusDAO" ref="StusDAO"></property>
	</bean>
</beans>

中转的action为

package com.undergrowth.action;

import java.util.List;

import com.undergrowth.IStusDAO;
import com.undergrowth.Stus;

public class StusAction {
	
	private List<Stus> listPerson;
	private IStusDAO stusDAO;
	
	public IStusDAO getStusDAO() {
		return stusDAO;
	}

	public void setStusDAO(IStusDAO stusDAO) {
		this.stusDAO = stusDAO;
	}

	public List<Stus> getListPerson() {
		return listPerson;
	}

	public void setListPerson(List<Stus> listPerson) {
		this.listPerson = listPerson;
	}
	
	
	public String getList()
	{
		this.listPerson=stusDAO.findAll();
		return "list";
	}
	
}

页面前段显示的界面,如下

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>信息列表</title>
</head>
<body>
	<s:iterator value="listPerson">
		<s:property/>
	</s:iterator>
</body>
</html>


持久层的Stus.java

package com.undergrowth;

import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Stus entity. @author MyEclipse Persistence Tools
 */
@Entity
@Table(name = "STUS", schema = "UNDER")
public class Stus implements java.io.Serializable {

	// Fields

	private String stuId;
	private String stuName;
	private Double stuAge;
	private Timestamp stuBirthday;

	// Constructors

	/** default constructor */
	public Stus() {
	}

	/** full constructor */
	public Stus(String stuId, String stuName, Double stuAge,
			Timestamp stuBirthday) {
		this.stuId = stuId;
		this.stuName = stuName;
		this.stuAge = stuAge;
		this.stuBirthday = stuBirthday;
	}

	// Property accessors
	@Id
	@Column(name = "STU_ID", unique = true, nullable = false, length = 50)
	public String getStuId() {
		return this.stuId;
	}

	public void setStuId(String stuId) {
		this.stuId = stuId;
	}

	@Column(name = "STU_NAME", nullable = false, length = 30)
	public String getStuName() {
		return this.stuName;
	}

	public void setStuName(String stuName) {
		this.stuName = stuName;
	}

	@Column(name = "STU_AGE", nullable = false, precision = 0)
	public Double getStuAge() {
		return this.stuAge;
	}

	public void setStuAge(Double stuAge) {
		this.stuAge = stuAge;
	}

	@Column(name = "STU_BIRTHDAY", nullable = false, length = 7)
	public Timestamp getStuBirthday() {
		return this.stuBirthday;
	}

	public void setStuBirthday(Timestamp stuBirthday) {
		this.stuBirthday = stuBirthday;
	}

	@Override
	public String toString() {
		return "Stus [stuId=" + stuId + ", stuName=" + stuName + ", stuAge="
				+ stuAge + ", stuBirthday=" + stuBirthday + "]";
	}

	
	
}

数据访问层StusDao.java

package com.undergrowth;

import java.sql.Timestamp;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * A data access object (DAO) providing persistence and search support for Stus
 * entities. Transaction control of the save(), update() and delete() operations
 * can directly support Spring container-managed transactions or they can be
 * augmented to handle user-managed Spring transactions. Each of these methods
 * provides additional information for how to configure it for the desired type
 * of transaction control.
 * 
 * @see com.undergrowth.Stus
 * @author MyEclipse Persistence Tools
 */
@Transactional
@Repository
public class StusDAO implements IStusDAO {
	private static final Log logger = LogFactory.getLog(StusDAO.class);
	// property constants
	public static final String STU_NAME = "stuName";
	public static final String STU_AGE = "stuAge";

	private EntityManager entityManager;

	@PersistenceContext
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	private EntityManager getEntityManager() {
		return entityManager;
	}

	/**
	 * Perform an initial save of a previously unsaved Stus entity. All
	 * subsequent persist actions of this entity should use the #update()
	 * method. This operation must be performed within the a database
	 * transaction context for the entity's data to be permanently saved to the
	 * persistence store, i.e., database. This method uses the
	 * {@link javax.persistence.EntityManager#persist(Object)
	 * EntityManager#persist} operation.
	 * <p>
	 * User-managed Spring transaction example:
	 * 
	 * <pre>
	 * TransactionStatus txn = txManager
	 * 		.getTransaction(new DefaultTransactionDefinition());
	 * StusDAO.save(entity);
	 * txManager.commit(txn);
	 * </pre>
	 * 
	 * @see <a href =
	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
	 *      container-managed transaction examples</a>
	 * @param entity
	 *            Stus entity to persist
	 * @throws RuntimeException
	 *             when the operation fails
	 */
	public void save(Stus entity) {
		logger.info("saving Stus instance");
		try {
			getEntityManager().persist(entity);
			logger.info("save successful");
		} catch (RuntimeException re) {
			logger.error("save failed", re);
			throw re;
		}
	}

	/**
	 * Delete a persistent Stus entity. This operation must be performed within
	 * the a database transaction context for the entity's data to be
	 * permanently deleted from the persistence store, i.e., database. This
	 * method uses the {@link javax.persistence.EntityManager#remove(Object)
	 * EntityManager#delete} operation.
	 * <p>
	 * User-managed Spring transaction example:
	 * 
	 * <pre>
	 * TransactionStatus txn = txManager
	 * 		.getTransaction(new DefaultTransactionDefinition());
	 * StusDAO.delete(entity);
	 * txManager.commit(txn);
	 * entity = null;
	 * </pre>
	 * 
	 * @see <a href =
	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
	 *      container-managed transaction examples</a>
	 * @param entity
	 *            Stus entity to delete
	 * @throws RuntimeException
	 *             when the operation fails
	 */
	public void delete(Stus entity) {
		logger.info("deleting Stus instance");
		try {
			entity = getEntityManager().getReference(Stus.class,
					entity.getStuId());
			getEntityManager().remove(entity);
			logger.info("delete successful");
		} catch (RuntimeException re) {
			logger.error("delete failed", re);
			throw re;
		}
	}

	/**
	 * Persist a previously saved Stus entity and return it or a copy of it to
	 * the sender. A copy of the Stus entity parameter is returned when the JPA
	 * persistence mechanism has not previously been tracking the updated
	 * entity. This operation must be performed within the a database
	 * transaction context for the entity's data to be permanently saved to the
	 * persistence store, i.e., database. This method uses the
	 * {@link javax.persistence.EntityManager#merge(Object) EntityManager#merge}
	 * operation.
	 * <p>
	 * User-managed Spring transaction example:
	 * 
	 * <pre>
	 * TransactionStatus txn = txManager
	 * 		.getTransaction(new DefaultTransactionDefinition());
	 * entity = StusDAO.update(entity);
	 * txManager.commit(txn);
	 * </pre>
	 * 
	 * @see <a href =
	 *      "http://www.myeclipseide.com/documentation/quickstarts/jpaspring#containermanaged">Spring
	 *      container-managed transaction examples</a>
	 * @param entity
	 *            Stus entity to update
	 * @return Stus the persisted Stus entity instance, may not be the same
	 * @throws RuntimeException
	 *             if the operation fails
	 */
	public Stus update(Stus entity) {
		logger.info("updating Stus instance");
		try {
			Stus result = getEntityManager().merge(entity);
			logger.info("update successful");
			return result;
		} catch (RuntimeException re) {
			logger.error("update failed", re);
			throw re;
		}
	}

	public Stus findById(String id) {
		logger.info("finding Stus instance with id: " + id);
		try {
			Stus instance = getEntityManager().find(Stus.class, id);
			return instance;
		} catch (RuntimeException re) {
			logger.error("find failed", re);
			throw re;
		}
	}

	/**
	 * Find all Stus entities with a specific property value.
	 * 
	 * @param propertyName
	 *            the name of the Stus property to query
	 * @param value
	 *            the property value to match
	 * @return List<Stus> found by query
	 */
	@SuppressWarnings("unchecked")
	public List<Stus> findByProperty(String propertyName, final Object value) {
		logger.info("finding Stus instance with property: " + propertyName
				+ ", value: " + value);
		try {
			final String queryString = "select model from Stus model where model."
					+ propertyName + "= :propertyValue";
			Query query = getEntityManager().createQuery(queryString);
			query.setParameter("propertyValue", value);
			return query.getResultList();
		} catch (RuntimeException re) {
			logger.error("find by property name failed", re);
			throw re;
		}
	}

	public List<Stus> findByStuName(Object stuName) {
		return findByProperty(STU_NAME, stuName);
	}

	public List<Stus> findByStuAge(Object stuAge) {
		return findByProperty(STU_AGE, stuAge);
	}

	/**
	 * Find all Stus entities.
	 * 
	 * @return List<Stus> all Stus entities
	 */
	@SuppressWarnings("unchecked")
	public List<Stus> findAll() {
		logger.info("finding all Stus instances");
		try {
			final String queryString = "select model from Stus model";
			Query query = getEntityManager().createQuery(queryString);
			return query.getResultList();
		} catch (RuntimeException re) {
			logger.error("find all failed", re);
			throw re;
		}
	}

	public static IStusDAO getFromApplicationContext(ApplicationContext ctx) {
		return (IStusDAO) ctx.getBean("StusDAO");
	}
}

5.测试效果如下



数据库中截图



以上步骤即是struts、spring、jpa的集成,当然相应的添加、修改、删除操作也是类似的,就不写了


6.遇到的问题

严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stusAction' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type '$Proxy21 implementing com.undergrowth.IStusDAO,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'com.undergrowth.StusDAO' for property 'stusDAO'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy21 implementing com.undergrowth.IStusDAO,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.undergrowth.StusDAO] for property 'stusDAO': no matching editors or conversion strategy found
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:385)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:284)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
	at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1113)
	at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1671)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type '$Proxy21 implementing com.undergrowth.IStusDAO,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'com.undergrowth.StusDAO' for property 'stusDAO'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy21 implementing com.undergrowth.IStusDAO,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.undergrowth.StusDAO] for property 'stusDAO': no matching editors or conversion strategy found
	at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:485)

上面的错误是说在StusAction进行依赖注入的时候stusDao的类型不匹配,原因在于spring容器在进行注入的时候,为stusDao生成代理对象的时候,采用的是jdk的动态代理,但是jdk的动态代理有一个前提就是,目标对象和代理对象有一个共同的接口,所以会造成类型不匹配


解决方案如下:



posted on 2014-02-16 20:57  liangxinzhi  阅读(239)  评论(0编辑  收藏  举报