一。事务说明
模拟用户购买商品(模拟用户下订单,向订单表添加销售记录,从商品表减少库存)
二。代码实现
1)创建数据库中的表—goods表和sale表
create table sale(
id int primary key auto_increment,
gid int ,
nums int
);
create table goods(
id int primary key auto_increment,
name varchar(100),
amount int,
price float
);
insert into goods values(1001,'computer',10,5000.00);
insert into goods values(1002,'phone',30,3000.00);
2)加入依赖
1.spring依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
2.mybatis依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
3.mysql驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
4.spring事务的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
5.spring和mybatis的集成依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
6.连接池
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
3)创建实体类
Goods类
package zjc.javaweb.entity;
public class Goods {
private Integer id;
private String name;
private Integer amount;
private float price;
}
Sale类
package zjc.javaweb.entity;
public class Sale {
private Integer id;
private Integer gid;
private Integer nums;
}
4)定义dao接口(mybatis内容)
GoodsDao
package zjc.javaweb.dao;
public interface GoodsDao {
int updateGoods(Goods goods);
}
SaleDao
package zjc.javaweb.dao;
public interface SaleDao {
int insertSale();
}
5)定义dao接口的sql映射文件,也即是同名xml文件(mybatis内容)
GoodsDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="zjc.javaweb.dao.GoodsDao">
<!--这个位置namespace要改成接口名字相对路径-->
<!--id改成dao接口的方法名-->
<update id="updateGoods">
<!--sql语句-->
update goods set amount =amount-#{amount}
</update>
<select id="selectGoods" resultType="Integer">
select amount from goods where id=#{goodsId}
</select>
</mapper>
这段代码应用率和重复率较高,大家可以参考我的另一篇文章来设置模板https://editor.csdn.net/md/?articleId=115414716
SaleDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="zjc.javaweb.dao.SaleDao">
<!--这个位置namespace要改成接口名字相对路径-->
<!--id改成dao接口的方法名-->
<insert id="insertSale">
<!--sql语句-->
insert into sale (gid,nums) values(#{gid},#{nums})
</insert>
</mapper>
6)定义service接口(spring内容)
package zjc.javaweb.Service;
public interface BuyGoodsService {
public void Buy(Integer goodsId,Integer amount);
}
7)定义service接口的实现类(spring内容)
package zjc.javaweb.Service;
import zjc.javaweb.dao.GoodsDao;
import zjc.javaweb.dao.SaleDao;
import zjc.javaweb.entity.Goods;
import zjc.javaweb.entity.Sale;
import zjc.javaweb.excep.NotEnoughException;
public class BuyGoodsServiceImp implements BuyGoodsService{
//1.dao属性
private SaleDao saleDao;
private GoodsDao goodsDao;
public void setSaleDao(SaleDao saleDao) {
this.saleDao = saleDao;
}
public void setGoodsDao(GoodsDao goodsDao) {
this.goodsDao = goodsDao;
}
@Override
public void Buy(Integer goodsId, Integer nums) {
//记录销售信息,向Sale表添加记录
Sale sale=new Sale();
sale.setGid(goodsId);
sale.setNums(nums);
saleDao.insertSale(sale);
//输出剩余库存
Goods goods=goodsDao.selectGoods(goodsId);
if(goods.getAmount()<nums){
System.out.println("库存不足");
}else{
int i=goods.getAmount()-nums;
System.out.println("购买成功,还剩"+i);
}
//更新库存
Goods buyGoods=new Goods();
buyGoods.setId(goodsId);
buyGoods.setAmount(nums);
goodsDao.updateGoods(buyGoods);
}
}
8)声明主配置文件和mybatis.xml文件
Resources文件下创建
mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--这里是设置输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<!--实体类的包名-->
<package name="zjc.javaweb.entity"/>
</typeAliases>
<mappers>
<!--是mapper配置文件的包名-->
<package name="zjc.javaweb.dao"/>
</mappers>
</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: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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--配置druid连接池数据源-->
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="333"/>
</bean>
<!--注册sqlsessionactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<!--value改成classpath:mybatis主配置文件的名字-->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<!--声明扫描器对象-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--dao接口所在路径-->
<property name="basePackage" value="zjc.javaweb.dao"/>
</bean>
<!--id:自己定义,class:是实现类的绝对路径-->
<bean id="buyService" class="zjc.javaweb.Service.BuyGoodsServiceImp">
<!--name是实现类中dao接口创建的属性,ref与前者同名-->
<property name="goodsDao" ref="goodsDao"/>
<property name="saleDao" ref="saleDao"/>
</bean>
<context:component-scan base-package="com.alibaba.druid">
</context:component-scan>
</beans>
9)定义测试类
package zjc.javaweb;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import zjc.javaweb.Service.BuyGoodsService;
public class AppTest
{
@Test
public void test01(){
String config="applicationContext.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
BuyGoodsService service=(BuyGoodsService) ac.getBean("buyService"); //service层定义id
service.Buy(1001,2);
}
}
接下来开始添加事务:
1)添加aspectJ依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
2)声明事务处理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--指定数据源-->
<property name="dataSource" ref="datasource"/>
</bean>
3)声明方法需要的事务类型
(配置方法的事务属性【隔离级别,传播行为,指定的异常】)
(isolation,propagation,rollback-for)
<!--声明业务方法的事务属性-->
<!--transaction-manager:事务管理器的id-->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<!--配置事务属性-->
<tx:attributes>
<!--给具体的事务方法配置事务属性,method可以有多个,给不同方法配置属性-->
<!--name可以写方法名,也可以用 add*(所有add开头的方法,也可以用*(全部方法))-->
<tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
rollback-for="zjc.javaweb.excep.NotEnoughException,java.lang.NullPointerException" />
<!--异常要写异常的全限定名称-->
</tx:attributes>
</tx:advice>
4)配置aop
<aop:config>
<aop:pointcut id="servicePt" expression="execution(* *..Service..*.*(..))"/>
<!--声明增强器,通知和切入点的组合-->
<aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/>
</aop:config>