ABCD 是一个事务,有4个业务
Connection conn = null;
try {
// 1、获得连接
conn = ...;
// 2、开启事务
conn.setAutoCommit(false);
A
B
C
D
// 3、提交事务
conn.commit();
} catch() {
// 4、回滚事务
conn.rollback();
}
需求:AB(必须业务),CD(可选业务)
Connection conn = null;
Savepoint savepoint = null; // 定义保存点,记录操作的当前位置,之后可以回滚到指定的位置。(可以回滚一部分)
try {
// 1、获得连接
conn = ...;
// 2、开启事务
conn.setAutoCommit(false);
A
B
savepoint = conn.setSavepoint();
C
D
// 3、提交事务
conn.commit();
} catch() {
if (savepoint != null) { // 说明CD异常
// 回滚到CD之前
conn.rollback(savepoint);
// 提交AB
conn.commit();
} else { // 说明AB异常
// 回滚AB之前
conn.rollback();
}
}
transaction --> tx
spring要管理事务,必须使用事务管理器
进行事务配置时,必须配置事务管理器。传播行为:在两个业务之间如何共享事务
。每个值的详解如下:
掌握:PROPAGATION_REQUIRED
、PROPAGATION_REQUIRES_NEW
、PROPAGATION_NESTED
1.3.1.1、创建表
CREATE DATABASE day35;
USE day35;
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
money INT
);
INSERT INTO account(username, money) VALUES('jack', '10000');
INSERT INTO account(username, money) VALUES('rose', '10000');
1.3.1.2、导入jar包
1.3.1.3、dao层
AccountDao.java
package com.itheima.dao;
public interface AccountDao {
/**
* 汇款
*
* @param outer
* @param money
*/
public void out(String outer, Integer money);
/**
* 收款
*
* @param inner
* @param money
*/
public void in(String inner, Integer money);
}
AccountDaoImpl.java
package com.itheima.dao.Impl;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.itheima.dao.AccountDao;
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
@Override
public void out(String outer, Integer money) {
this.getJdbcTemplate().update("update account set money=money-? where username=?", money, outer);
}
@Override
public void in(String inner, Integer money) {
this.getJdbcTemplate().update("update account set money=money+? where username=?", money, inner);
}
}
1.3.1.4、service层 AccountService.java
package com.itheima.service;
public interface AccountService {
/**
* 转账
*
* @param outer
* @param inner
* @param money
*/
public void transfer(String outer, String inner, Integer money);
}
AccountServiceImpl.java
package com.itheima.service.impl;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
public class AccountServiceImpl implements AccountService{
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, Integer money) {
accountDao.out(outer, money);
// 断电
// int i = 1/0; // 断电会出现事务问题
accountDao.in(inner, money);
}
}
1.3.1.5、spring配置 为了更加接近实际开发,配置文件的名称改为 applicationContext.xml,配置文件的位置放在 src目录下。 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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- datasource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/day35"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- dao -->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
</beans>
1.3.1.6、测试 TestApp.java
package com.itheima;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.service.AccountService;
public class TestApp {
@Test
public void demo01() {
String xmlPath = "applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
AccountService accountService = (AccountService) applicationContext.getBean("accountService");
accountService.transfer("jack", "rose", 100);
}
}
1.3.2.1、修改service层代码 AccountServiceImpl.java
package com.itheima.service.impl;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
public class AccountServiceImpl implements AccountService{
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
// 需要Spring注入模板
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Override
public void transfer(final String outer, final String inner, final Integer money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.out(outer, money);
// 断电
int i = 1/0; // 断电会出现事务问题
accountDao.in(inner, money);
}
});
}
}
1.3.2.2、修改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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- datasource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/day35"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- dao -->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>
<!-- 创建模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager"></property>
</bean>
<!-- 配置事务管理器,注意:事务管理器需要事务,而事务从 连接Connection 获得,而 连接Connection 从 连接池DataSource 处获得 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
1.3.3.1、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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- datasource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/day35"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- dao -->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- service 的代理对象
4.1 proxyInterfaces 接口
4.2 target 目标类
4.3 transactionManager 事务管理器
4.4 transactionAttributes 事务属性(事务详情)
prop.key :确定哪些方法使用当前事务配置
prop.text :用于配置事务详情
格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception
传播行为 隔离级别 是否只读 发生异常后仍然异常回滚事务 发生异常后仍然提交事务
例如:
<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop> 默认传播行为,和默认隔离级别
<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly</prop> 只读
<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,+java.lang.ArithmeticException</prop> 发生异常后仍然提交事务
-->
<bean id="proxyAccountService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="preInterceptors" value="com.itheima.service.AccountService"></property>
<property name="target" ref="accountService"></property>
<property name="transactionManager" ref="txManager"></property>
<property name="transactionAttributes">
<props>
<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop> <!-- 默认传播行为,和默认隔离级别 -->
</props>
</property>
</bean>
<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
1.3.3.2、测试 TestApp.java
package com.itheima;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.service.AccountService;
public class TestApp {
@Test
public void demo01() {
String xmlPath = "applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
AccountService accountService = (AccountService) applicationContext.getBean("proxyAccountService");
accountService.transfer("jack", "rose", 100);
}
}
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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.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">
<!-- datasource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/day35"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- dao -->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 事务管理 -->
<!-- 4.1 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 4.2 事务详情(事务通知),在 aop编程 筛选的基础上,对ABC三个确定使用什么样的事务。例如:AC读写、B只读 等等。
<tx:attributes> 用于配置事务详情(属性属性)
<tx:method name=""/> 详情具体配置
propagation 传播行为 , REQUIRED:必须; REQUIRES_NEW:必须是新的
isolation 隔离级别
-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!-- 4.3 AOP编程,例如:我们的目标类有ABCD(4个连接点),使用切入点表达式,确定需要增强的连接点,从而获得切入点:ABC -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service..*.*(..))"/>
</aop:config>
</beans>
1.3.5.1、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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.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">
<!-- datasource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/day35"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- dao -->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 事务管理 -->
<!-- 4.1 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 4.2 将事务管理器交予spring管理
* transaction-manager 配置事务管理器
* proxy-target-class
true : 底层强制使用 cglib代理
false :默认的值为false
-->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="false"/>
</beans>
1.3.5.2、service 层 AccountServiceImpl.java
package com.itheima.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
@Transactional
public class AccountServiceImpl implements AccountService{
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, Integer money) {
accountDao.out(outer, money);
// 断电
// int i = 1/0; // 断电会出现事务问题
accountDao.in(inner, money);
}
}
1.3.5.3、事务详情配置
AccountServiceImpl.java
package com.itheima.service.impl;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
@Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.DEFAULT)
public class AccountServiceImpl implements AccountService{
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, Integer money) {
accountDao.out(outer, money);
// 断电
// int i = 1/0; // 断电会出现事务问题
accountDao.in(inner, money);
}
}
步骤如下:
TestApp.java
package com.itheima;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.itheima.service.AccountService;
// 1、让Junit去通知spring加载配置文件
// 2、让spring容器自动进行注入
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class TestApp {
@Autowired // 这是与junit整合,不需要在spring xml中进行配置扫描
private AccountService accountService;
@Test
public void demo01() {
// String xmlPath = "applicationContext.xml";
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// AccountService accountService = (AccountService) applicationContext.getBean("accountService");
accountService.transfer("jack", "rose", 100);
}
}
步骤如下:
0、导入jar包
spring-web-3.2.0.RELEASE.jar
1、tomcat启动时就加载配置文件的方案:
方案1:servlet --> init(ServletConfig) --> <load-on-startup>2
方案2:filter --> init(FilterConfig) --> web.xml注册过滤器后,就会自动调用初始化
方案3:listener --> ServletContextListener --> servletContext对象监听
方案4:spring提供了一个监听器 ContextLoaderListener --> web.xml (<listener><listener-class>...)
如果只配置了监听器,则默认加载xml文件的位置为:/WEB-INF/applicationContext.xml
2、确定配置文件位置,通过系统初始化参数
ServletContext的初始化参数配,在web.xml文件中进行配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
3、从servletContext作用域中获得spring容器(了解即可,很少用)
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>day35_04_Spring_tx</display-name>
<!-- 确定配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 配置spring 监听器,用于加载xml配置文件 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.itheima.web.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
HelloServlet.java
package com.itheima.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.itheima.service.AccountService;
public class HelloServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 从application作用域(ServletContext)获得spring容器
// 方式1: 手动从作用域获取
ApplicationContext applicationContext = (ApplicationContext) this.getServletContext()
.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
// 方式2:通过工具类获取
ApplicationContext apppApplicationContext2 = WebApplicationContextUtils
.getWebApplicationContext(this.getServletContext());
// 转账操作
AccountService accountService = (AccountService) applicationContext.getBean("accountService");
accountService.transfer("jack", "rose", 1000);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
create table t_user(
id int primary key auto_increment,
username varchar(50),
password varchar(32),
age int
);
User.java
package com.itheima.domain;
public class User {
/*
* CREATE TABLE t_user(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
PASSWORD VARCHAR(32),
age INT
);
*/
private Integer id;
private String username;
private String password;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
映射文件User.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.itheima.domain.User" table="t_user">
<id name="id">
<generator class="native"></generator>
</id>
<property name="username"></property>
<property name="password"></property>
<property name="age"></property>
</class>
</hibernate-mapping>
UserDao.java
package com.itheima.dao;
import com.itheima.domain.User;
public interface UserDao {
/**
* 保存
*
* @param user
*/
public void save(User user);
}
UserDaoImpl.java
package com.itheima.dao.impl;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
public class UserDaoImpl implements UserDao {
// 需要Spring注入模板
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
@Override
public void save(User user) {
this.hibernateTemplate.save(user);
}
}
UserService.java
package com.itheima.service;
import com.itheima.domain.User;
public interface UserService {
/**
* 注册
*
* @param user
*/
public void register(User user);
}
UserServiceImpl.java
package com.itheima.service.impl;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void register(User user) {
userDao.save(user);
}
}
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 1、基本四项 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/day35</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 2、配置方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 3、sql语句 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- 4、自动生成表结构(一般没用,因为真正的开发中是先建模,然后通过工具自动生成表结构、SQL语句 等) -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 5、本地线程绑定(用处不大,因为事务我们交给Spring管理了) -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 6、导入映射文件 -->
<mapping resource="com/itheima/domain/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1、加载hibenrate.cfg.xml,获得 SessionFactory(小结:jdbc开发需要数据源DataSource,hibernate开发需要SessionFactory)
* configLocation 确定配置文件位置
-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
</bean>
<!-- 2、先创建模板
* 需要Spring注入模板,该底层使用的就是session,而session是由SessionFactory获得的
-->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 3、dao -->
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
<!-- 4、service -->
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 5、事务管理
5.1、事务管理器 :HibernateTransactionManager
-->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 5.2、事务详情 ,给ABC进行具体的事务设置 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="register"/>
</tx:attributes>
</tx:advice>
<!-- 5.3、AOP编程,从 ABCD 业务中 筛选出 ABC -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service..*.*(..))"/>
</aop:config>
</beans>
TestApp.java
package com.itheima;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.itheima.domain.User;
import com.itheima.service.UserService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class TestApp {
@Autowired
private UserService userService;
@Test
public void demo01(){
User user = new User();
user.setUsername("bruce");
user.setPassword("123456");
user.setAge(26);
userService.register(user);
}
}
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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.1、加载properties文件 -->
<!-- 1.2、配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///day35"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 1.3、配置 LocalSessionFactoryBean,获得SessionFactory
* configLocation确定配置文件位置
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
1)dataSource 数据源
2)hibernateProperties hibernate其他配置项
3)导入映射文件
mappingLocations ,确定映射文件位置,需要加“classpath:”。支持通配符 【常使用】
<property name="mappingLocations" value="classpath:com/itheima/domain/User.hbm.xml"></property> 或者
<property name="mappingLocations" value="classpath:com/itheima/domain/*.hbm.xml"></property>
mappingResources ,加载指定的映射文件,默认从src下开始,不需要加“classpath:” 。不支持通配符*
<property name="mappingResources" value="com/itheima/domain/User.hbm.xml"></property>
mappingDirectoryLocations ,加载指定目录下的,所有配置文件
<property name="mappingDirectoryLocations" value="classpath:com/itheima/domain/"></property>
mappingJarLocations ,从jar包中获得映射文件
-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
<property name="mappingLocations" value="classpath:com/itheima/domain/*.hbm.xml"></property>
</bean>
<!-- 3、dao spring中删除模板,给dao注入SessionFactory-->
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 4、service -->
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 5 、事务管理
5.1、 事务管理器 :HibernateTransactionManager
-->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 5.2 、事务详情 ,给ABC进行具体的事务设置 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="register"/>
</tx:attributes>
</tx:advice>
<!-- 5.3、AOP编程,从 ABCD 业务中 筛选出 ABC -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service..*.*(..))"/>
</aop:config>
</beans>
UserDaoImpl.java
package com.itheima.dao.impl;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
// 底层需要SessionFactory,会自动创建HibernateTemplate模板
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
@Override
public void save(User user) {
this.getHibernateTemplate().save(user);
}
}
操作步骤如下:
UserAction.java
package com.itheima.web.action;
import com.itheima.domain.User;
import com.itheima.service.UserService;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class UserAction extends ActionSupport implements ModelDriven<User> {
// 1、封装数据
private User user = new User();
@Override
public User getModel() {
return user;
}
// 2、service
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
/**
* 注册功能
*
* @return
*/
public String register() {
userService.register(user);
return "success";
}
}
applicationContext.xml
......
<!-- 6、配置action,并配置多例 -->
<bean id="userAction" class="com.itheima.web.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
......
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 开发模式 -->
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<!-- 底层自动从spring容器中通过名称获得内容, getBean("userAction") -->
<action name="userAction_*" class="userAction" method="{1}">
<result name="success">/message.jsp</result>
</action>
</package>
</struts>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/userAction_register" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" />
</form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!-- 1、确定Spring xml的位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 2、spring 的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 3、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>
</web-app>
操作步骤如下:
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 开发模式 -->
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<!-- 底层自动从spring容器中通过名称获得内容, getBean("userAction") -->
<action name="userAction_*" class="com.itheima.web.action.UserAction" method="{1}">
<result name="success">/message.jsp</result>
</action>
</package>
</struts>
打开struts-plugins.xml文件后,有如下一句代码:
< constant name="struts.objectFactory" value="spring" /> 该配置说明:struts的action将由spring创建
综上所述:之后的action由spring创建,并按照名称自动注入
。