Spring—SSJ集成&聲明式事務管理

1.   課程介紹

  • 1.  SSJ集成;(掌握)
  • 2.  聲明式事務管理;(掌握)
  1. 什麼是三大框架

2.1.  sshjava

Struts/Struts2 Spring Hibernatemysql

2.2.  ssmweb

SpringMVC Spring MyBatisspring

2.3.  ssjsql

Struts2 Spring JPA數據庫

SpringMVC Spring JPAapache

SpringMVC Spring Data JPAtomcat

  1. Spring集成JPA;(掌握)

Spring4 + Struts2 + jpa/hibernate4app

建議:先完成Spring與jpa的集成框架

3.1.  建立動態web工程:

注意修改classpath路徑,建立web文件取名爲webapp

3.2.  拷貝Spring共16的jar文件

11個spring的jar文件

spring-framework-3.2.0.RELEASE-dependencies搜索dbcp,pool,aop,wea,logging

 

3.3.  拷貝JPA共11的jar文件

hibernate-release-4.3.8.Final\lib\jpa\*.jar

hibernate-release-4.3.8.Final\lib\required\*.jar

 

3.4.  拷貝數據庫驅動1個jar文件

Spring+jpa+驅動共28個jar文件

3.5.  寫一個domain對象,配置JPA映射

@Entity

@Table(name = "t_product")

public class Product {

         @Id

         @GeneratedValue

         private Long id;

         private String name;

3.6.  Spring的配置文件

3.6.1.   Bean對象注入的順序

jdbc.properties->dataSource->entityManagerFactory->dao->service->junit->action

3.6.2.   加載jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql:///ssj

jdbc.username=root

jdbc.password=root

 

<?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:context="http://www.springframework.org/schema/context"

         xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd">

 

         <!-- 加載jdbc.properties -->

         <context:property-placeholder location="jdbc.properties" />

3.6.3.   配置鏈接池dataSource

<!-- 配置鏈接池dataSource -->

<!-- destroy-method="close當前bean銷燬的時候,會先調用close方法,關閉鏈接" -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

         <!-- 依賴注入鏈接池須要的屬性 -->

         <!-- property name="是BasicDataSource的set方法,本質屬性" -->

         <!-- property value="是jdbc.properties配置文件的key" -->

         <property name="driverClassName" value="${jdbc.driverClassName}" />

         <property name="url" value="${jdbc.url}" />

         <property name="username" value="${jdbc.username}" />

         <property name="password" value="${jdbc.password}" />

</bean>

3.7.  配置entityManagerFactory

3.7.1.   Spring-Reference_2.5_zh_CN.chm

 

12.6.1.3. LocalContainerEntityManagerFactoryBean

 

3.7.2.   配置信息

<!-- org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter引入默認entityManagerFactory名稱 -->

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

         <!-- 1.注入DataSource -->

         <property name="dataSource" ref="dataSource" />

         <!-- 2.從哪一個包去掃描@Entity,domain包 -->

         <!-- public void setPackagesToScan(String... packagesToScan) { -->

         <property name="packagesToScan" value="cn.itsource.ssj.domain" />

         <!-- 3.配置JPA的實現 -->

         <!-- private JpaVendorAdapter jpaVendorAdapter; -->

         <property name="jpaVendorAdapter">

                  <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

                           <!-- org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter -->

                           <!-- private boolean showSql = false;是否顯示sql語句 -->

                           <property name="showSql" value="true" />

                           <!-- private boolean generateDdl = false;是否建表 -->

                           <property name="generateDdl" value="true" />

                           <!-- private String databasePlatform;原來方言 -->

                           <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />

                  </bean>

         </property>

</bean>

3.8.  IProductDao

public interface IProductDao {

         void save(Product product);

 

         void update(Product product);

 

         void delete(Long id);

 

         Product get(Long id);

 

         List<Product> getAll();

}

3.9.  ProductDaoImpl

@Repository

public class ProductDaoImpl implements IProductDao {

 

         // @Autowired 不能使用這個注入

         @PersistenceContext // 持久層上下文管理器

         private EntityManager entityManager;

 

         @Override

         public void save(Product product) {

                  entityManager.persist(product);

         }

 

         @Override

         public void update(Product product) {

                  entityManager.merge(product);

         }

 

         @Override

         public void delete(Long id) {

                  Product product = get(id);

                  if (product != null) {

                           entityManager.remove(product);

                  }

         }

 

         @Override

         public Product get(Long id) {

                  return entityManager.find(Product.class, id);

         }

 

         @Override

         public List<Product> getAll() {

                  String jpql = "select o from Product o";

                  return entityManager.createQuery(jpql).getResultList();

         }

 

}

3.10.         組件掃描

<!-- 掃描dao、service、action組件 -->

<!-- 能夠處理@Repository, @Service, and @Controller,@Autowired,@PersistenceContext 註解-->

<context:component-scan base-package="cn.itsource.ssj" />

3.11.         IProductService

public interface IProductService {

         void save(Product product);

 

         void update(Product product);

 

         void delete(Long id);

 

         Product get(Long id);

 

         List<Product> getAll();

}

3.12.         ProductServiceImpl

@Service

public class ProductServiceImpl implements IProductService {

         @Autowired

         private IProductDao productDao;

 

         @Override

         public void save(Product product) {

                  productDao.save(product);

         }

 

         @Override

         public void update(Product product) {

                  productDao.update(product);

         }

 

         @Override

         public void delete(Long id) {

                  productDao.delete(id);

         }

 

         @Override

         public Product get(Long id) {

                  return productDao.get(id);

         }

 

         @Override

         public List<Product> getAll() {

                  return productDao.getAll();

         }

 

}

3.13.         聲明式事務管理(註解版本)

在spring的配置文件添加一點事務配置,而且在service層類上面添加一些註解,就能夠實現事務管理

3.13.1.        添加一個tx命名空間

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

         xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd">

3.13.2.        添加事務配置

<!-- 配置事務管理器 -->

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

         <property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>

<!-- 開啓註解事務管理 ,解析@Transactional事務註解 -->

<!-- transaction-manager="transactionManager"默認找bean.id=transactionManager事務管理器 -->

<tx:annotation-driven />

3.13.3.        ProductServiceImpl

@Service

// 默認事務配置

// @Transactional

// 上面配置等價於下面配置

@Transactional(propagation = Propagation.REQUIRED)

public class ProductServiceImpl implements IProductService {

         @Autowired

         private IProductDao productDao;

 

         @Override

         public void save(Product product) {

                  productDao.save(product);

         }

 

         @Override

         public void update(Product product) {

                  productDao.update(product);

         }

 

         @Override

         public void delete(Long id) {

                  productDao.delete(id);

         }

 

         @Override

         @Transactional(readOnly=true,propagation=Propagation.SUPPORTS)

         public Product get(Long id) {

                  return productDao.get(id);

         }

 

         @Override

         @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)

         public List<Product> getAll() {

                  return productDao.getAll();

         }

 

}

3.14.         Junit

@Autowired

IProductService productService;

 

@Test

public void save() throws Exception {

         System.out.println("代理類:" + productService.getClass());

         Product product = new Product();

         product.setName("蘋果的弟弟");

         productService.save(product);

}

代理類:class com.sun.proxy.$Proxy23

  1. Spring集成Struts2

4.1.  添加struts2的12個jar文件

沒有導入javassist-3.11.0.GA.jar

 

4.2.  配置web.xml

<!-- 添加struts核心過濾器 -->

<filter>

         <filter-name>struts2</filter-name>

         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

</filter>

 

<filter-mapping>

         <filter-name>struts2</filter-name>

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

</filter-mapping>

4.3.  配置struts.xml

<package name="default" namespace="/" extends="struts-default">

 

         <!-- action表明一個控制器, name="對應的訪問的url地址" method="返回action的方法" -->

         <!-- spring集成struts以後,class能夠寫全限定類名,也能夠寫bean.id -->

         <!-- product 沒有寫_的時候,默認就是訪問當前action的execute -->

         <!-- product_*寫了_input,訪問input方法 ,對應後面method={1} -->

 

         <action name="product_*" class="cn.itsource.ssj.action.ProductAction" method="{1}">

                  <!-- 顯示列表頁面 -->

                  <result>/WEB-INF/views/product.jsp</result>

                  <!-- 顯示添加獲取修改頁面 -->

                  <result name="input">/WEB-INF/views/product_input.jsp</result>

                  <!-- 保存或者刪除以後進行重定向 -->

                  <result name="reload" type="redirectAction">product</result>

         </action>

 

</package>

4.4.  ProductAction

public class ProductAction extends ActionSupport {

 

         @Autowired

         IProductService productService;

 

         @Override

         public String execute() throws Exception {

                  ActionContext.getContext().put("products", productService.getAll());

                  return SUCCESS;

         }

}

4.5.  配置好,啓動tomcat,拋出一下異常

4.5.1.   具體異常信息

嚴重: Exception starting filter struts2

Class: com.opensymphony.xwork2.spring.SpringObjectFactory

File: SpringObjectFactory.java

Method: getClassInstance

Line: 245 - com/opensymphony/xwork2/spring/SpringObjectFactory.java:245:-1

         at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:493)

         at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)

         at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.java:57)

         at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:279)

         at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:260)

         at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:105)

         at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4700)

         at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5340)

         at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)

         at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)

         at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)

         at java.util.concurrent.FutureTask.run(FutureTask.java:266)

         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

         at java.lang.Thread.run(Thread.java:745)

Caused by: java.lang.NullPointerException

         at com.opensymphony.xwork2.spring.SpringObjectFactory.getClassInstance(SpringObjectFactory.java:245)

         at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.verifyResultType(XmlConfigurationProvider.java:608)

         at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addResultTypes(XmlConfigurationProvider.java:578)

         at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addPackage(XmlConfigurationProvider.java:534)

         at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadPackages(XmlConfigurationProvider.java:295)

         at org.apache.struts2.config.StrutsXmlConfigurationProvider.loadPackages(StrutsXmlConfigurationProvider.java:112)

         at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:264)

         at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)

         at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:967)

         at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:435)

         at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:479)

         ... 14 more

4.5.2.   爲何會出現異常?

由於原來struts2的對象都是由xwork的對象處理,如今添加struts2-spring-plugin-2.3.20.jar文件,以後由spring接管了對原來struts2對象的建立

緣由是在struts2-spring-plugin-2.3.20.jar文件裏面有這個配置struts-plugin.xml

<struts>

    <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />

   

    <!--  Make the Spring object factory the automatic default -->

    <constant name="struts.objectFactory" value="spring" />

 

    <constant name="struts.class.reloading.watchList" value="" />

    <constant name="struts.class.reloading.acceptClasses" value="" />

    <constant name="struts.class.reloading.reloadConfig" value="false" />

 

    <package name="spring-default">

        <interceptors>

            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>

        </interceptors>

    </package>   

</struts>

而spring容器並無被啓動

4.5.3.   在web.xml添加一個監聽器,來實例化spring容器

<!-- 添加一個監聽器,來實例化spring容器 -->

<listener>

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

</listener>

4.5.4.   再次啓動tomcat,又拋出異常

Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]

         at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:141)

         at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:330)

         ... 21 more

默認會去WEB-INF下面找配置文件,而此路徑沒有

4.5.5.   在web.xml添加一個上下文的初始化參數,來告訴spring從哪裏加載配置文件

<!-- 添加一個上下文的初始化參數 -->

<context-param>

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

         <param-value>classpath:applicationContext.xml</param-value>

</context-param>

4.5.6.   怎樣快速找contextConfigLocation名字

找監聽器ContextLoaderListener的父類ContextLoader

有一個常量配置

public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";

4.5.7.   不能加載jdbc.properties異常

Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/jdbc.properties]

4.5.8.   修改spring的配置文件

<!-- 加載jdbc.properties -->

<!-- 跑web必須在前面添加classpath:前綴 -->

<context:property-placeholder location="classpath:jdbc.properties" />

4.5.9.   再次啓動tomcat,沒有異常

4.5.10.        訪問http://localhost/product,出現404異常,

由於沒有寫jsp頁面,此jsp頁面和原來寫JPA集成Struts2的jsp是一致的。

 

4.5.11.        product.jsp

<body>

         <table border="1">

                  <tr>

                           <th>編號</th>

                           <th>產品名稱</th>

<!--                   <th>產品類型名稱</th> -->

                           <th>操做</th>

                  </tr>

                  <s:iterator value="#products">

                           <tr>

                                    <td>${id}</td>

                                    <td>${name}</td>

<%--                                     <td>${dir.name}</td> --%>

                                    <td><a href="product_input?product.id=${id}">修改</a> <a

                                             href="product_delete?product.id=${id}">刪除</a></td>

                           </tr>

                  </s:iterator>

         </table>

         <a href="product_input">添加</a>

</body>

  1. 以一樣的方式添加產品類型

5.1.  添加產品類型模型

模型ProductDir,修改Product添加@ManyToOne

寫dao,service

5.2.  修改web.xml,解決延遲加載的異常

<!-- 添加關閉entityManger過濾器,必須在struts2過濾器以前 -->

<filter>

         <filter-name>OpenEntityManagerInViewFilter</filter-name>

         <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>

</filter>

 

<filter-mapping>

         <filter-name>OpenEntityManagerInViewFilter</filter-name>

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

</filter-mapping>

  1. struts.xml class屬性配置原理

6.1.  struts2加載配置文件順序

struts2-core-2.3.20.jar\org\apache\struts2\default.properties

struts2-core-2.3.20.jar\struts-default.xml

struts2-spring-plugin-2.3.20.jar\struts-plugin.xml

...

classpath:struts.xml

6.2.  struts2-spring-plugin-2.3.20.jar  struts-plugin.xml

沒有使用這個jar文件,struts2的對象建立是由xwork處理

添加這個這個jar文件以後struts2的對象就由spring建立

<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />

   

<!--  Make the Spring object factory the automatic default -->

<constant name="struts.objectFactory" value="spring" />

6.3.  default.properties

默認狀況下在struts.xml的action節點裏面class屬性寫全限定類名是按照byName注入

 

### valid values are: name, type, auto, and constructor (name is the default)

struts.objectFactory.spring.autoWire = name

 

6.4.  class屬性

6.4.1.   方案1 建議使用,填寫spring的bean  id,

注意xml版本配置scope=’prototype’

    註解版本配置@Scope(「prototype」)

 

好處1:可使用小寫的url地址,從使用通配符

<package name="default" namespace="/" extends="struts-default">

 

         <!-- action表明一個控制器, name="對應的訪問的url地址" method="返回action的方法" -->

 

         <!-- spring集成struts以後,class能夠寫全限定類名,也能夠寫bean.id -->

 

 

<!-- *_* 請求的url_請求的方法 -->

<!-- 第1個*表明url地址,好比如今product,後面使用{1}來代替,url地址小寫開頭,正好對應action的bean.id的定義 -->

<!-- 第2個*表明訪問action的方法,好比如今product_input,後面使用{2}來代替 -->

 

         <action name="*_*" class="{1}Action" method="{2}">

                  <!-- 顯示列表頁面 -->

                  <result>/WEB-INF/views/{1}.jsp</result>

                  <!-- 顯示添加獲取修改頁面 -->

                  <result name="input">/WEB-INF/views/{1}_input.jsp</result>

                  <!-- 保存或者刪除以後進行重定向 -->

                  <result name="reload" type="redirectAction">{1}</result>

         </action>

 

</package>

 

好處2:由於使用action是由spring管理

能夠對action添加aop額外處理

 

壞處:spring配置文件寫action的配置

@Controller//bean.id=productAction

@Scope("prototype")//配置多例

public class ProductAction extends ActionSupport {

6.4.2.   方案2 填寫全限定類名,

若是填寫全限定類名,則返回是小寫url的地址,要求cn.itsource.ssj.action.ProductAction,類名對應要小寫,不符合java命名規範;不能使用*_*通配符

@Autowired先按照類型,若是接口有2個實現,會報錯

能夠添加@Qualifier("productServiceImpl")名稱來進行注入

 

public class ProductAction extends ActionSupport {

         @Autowired

         private IProductService productService;

  1. 課程總結

7.1.  重點

Ssj集成必須寫熟練,1遍,2遍,3遍

7.2.  難點

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

         xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd">

 

         <!-- jdbc.properties->dataSource->entityManagerFactory->dao->service->junit->action -->

 

         <!-- 掃描dao、service、action組件 -->

         <!-- @Repository, @Service, and @Controller,@Autowired,@PersistenceContext -->

         <context:component-scan base-package="cn.itsource.ssj" />

 

<!-- 加載jdbc.properties -->

<!-- 跑web必須在前面添加classpath:前綴 -->

<context:property-placeholder location="classpath:jdbc.properties" />

 

         <!-- 配置鏈接池dataSource -->

         <!-- destroy-method="close當前bean銷燬的時候,會先調用close方法,關閉鏈接" -->

         <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

                  <!-- 依賴注入鏈接池須要的屬性 -->

                  <!-- property name="是BasicDataSource的set方法,本質屬性" -->

                  <!-- property value="是jdbc.properties配置文件的key" -->

                  <property name="driverClassName" value="${jdbc.driverClassName}" />

                  <property name="url" value="${jdbc.url}" />

                  <property name="username" value="${jdbc.username}" />

                  <property name="password" value="${jdbc.password}" />

         </bean>

 

         <!-- org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter引入默認entityManagerFactory名稱 -->

         <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

                  <!-- 1.注入DataSource -->

                  <property name="dataSource" ref="dataSource" />

                  <!-- 2.從哪一個包去掃描@Entity,domain包 -->

                  <!-- public void setPackagesToScan(String... packagesToScan) { -->

                  <property name="packagesToScan" value="cn.itsource.ssj.domain" />

                  <!-- 3.配置JPA的實現 -->

                  <!-- private JpaVendorAdapter jpaVendorAdapter; -->

                  <property name="jpaVendorAdapter">

                           <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

                                    <!-- org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter -->

                                    <!-- private boolean showSql = false;是否顯示sql語句 -->

                                    <property name="showSql" value="true" />

                                    <!-- private boolean generateDdl = false;是否建表 -->

                                    <property name="generateDdl" value="true" />

                                    <!-- private String databasePlatform;原來方言 -->

                                    <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />

                           </bean>

                  </property>

         </bean>

 

         <!-- 配置事務管理器 -->

         <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

                  <property name="entityManagerFactory" ref="entityManagerFactory" />

         </bean>

         <!-- 開啓註解事務管理 ,解析@Transactional註解 -->

         <!-- transaction-manager="transactionManager"默認找bean.id=transactionManager事務管理器 -->

         <tx:annotation-driven />

 

 

</beans>

  1. 常見異常
  2. javax.persistence.TransactionRequiredException: No transactional EntityManager available

事務沒有配置成功

沒有配置<tx:annotation-driven />

  1. No qualifying bean of type [cn.itsource.ssj.service.IProductService] is defined: expected single matching bean but found 2: productServiceImpl,productServiceImpl2

Could not autowire field: private cn.itsource.ssj.service.IProductService cn.itsource.ssj.action.ProductAction.productService; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of

type [cn.itsource.ssj.service.IProductService] is defined: expected single matching bean but found 2: productServiceImpl,productServiceImpl2

接口有2個實現

相關文章
相關標籤/搜索