1.创建复杂对象
复杂对象:类中没有构造方法或者构造方法不能调用,如接口类型或抽象类实例

新建Maven-webapp工程,添加java、resources目录
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>spring03</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>spring03 Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--spring核心及相关依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.4</version> </dependency> <!--mybatis-spring--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.4</version> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.19</version> </dependency> </dependencies> <build> <finalName>spring03</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
1.1 抽象类Calendar
CalendarFactoryBean.java
package factorybean;
import org.springframework.beans.factory.FactoryBean;
import java.util.Calendar;
/**
* @ClassName CalendarFactoryBean
* @Description 用来在工厂中创建复杂对象Calendar
* @Author Jiangnan Cui
* @Date 2022/4/7 21:33
* @Version 1.0
*/
public class CalendarFactoryBean implements FactoryBean<Calendar> {
//用来书写复杂对象的创建方式
@Override
public Calendar getObject() throws Exception {
return Calendar.getInstance();
}
//指定创建的复杂对象类型
@Override
public Class<?> getObjectType() {
return Calendar.class;
}
//用来指定创建的对象模式 true表示单例,false表示多例
@Override
public boolean isSingleton() {
return true;
}
}
spring.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--管理组件对象--> <bean class="factorybean.CalendarFactoryBean" id="calendar"/> </beans>
CalendarTest.java
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Calendar;
/**
* @ClassName CalendarTest
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/7 21:39
* @Version 1.0
*/
public class CalendarTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("factorybean/spring.xml");
Calendar calendar = (Calendar) context.getBean("calendar");
System.out.println(calendar);
Calendar calendar1 = (Calendar) context.getBean("calendar");
System.out.println(calendar1);
System.out.println(calendar==calendar1);
}
}
1.2 接口Connection
ConnectionFactoryBean.java
package factorybean;
import org.springframework.beans.factory.FactoryBean;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* @ClassName ConnectionFactoryBean
* @Description 用工厂创建复杂对象Connection
* @Author Jiangnan Cui
* @Date 2022/4/7 21:43
* @Version 1.0
*/
public class ConnectionFactoryBean implements FactoryBean<Connection> {
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis","root","123456");
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
spring.xml
<bean class="factorybean.ConnectionFactoryBean" id="connection"/>
ConnectionTest.java
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.sql.Connection;
/**
* @ClassName ConnectionTest
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/7 21:48
* @Version 1.0
*/
public class ConnectionTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("factorybean/spring.xml");
Connection connection = (Connection) context.getBean("connection");
System.out.println(connection);
Connection connection1 = (Connection) context.getBean("connection");
System.out.println(connection1);
System.out.println(connection==connection1);
}
}
2. SM整合思路
配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili
2.1 spring框架的作用
spring框架 项目管理框架 主要负责项目中组件对象的创建
2.2 Mybatis框架的作用
Mybatis框架 持久层框架 主要用来简化数据库访问的操作
2.3 整合思路
整合思路: 两个框架作用不同,貌似没有什么联系,更深入看才能看出所谓Spring整合Mybatis,其实就是通过spring框架接管mybatis框架中核心对象的创建
2.4 Mybatis中的核心对象
Mybatis的核心对象为: SqlSessionFactory整合就是通过Spring管理SqlSessionFactory对象的创建
2.5 整合思路
总体示意图:

Spring整合Mybatis思路分析:

Spring整合Mybatis编程步骤:

2.6 具体实现
(1)引入依赖
<!--spring核心及相关依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.4</version> </dependency> <!--mybatis-spring--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.4</version> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.19</version> </dependency>
(2)配置spring.xml
<!--创建sqlSessionFactory对象--> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"> <!--依赖数据源对象--> <property name="dataSource" ref="dataSource"/> <!--依赖mapper文件注册--> </bean> <!--创建数据源对象druid,需要引入druid依赖,类似的数据源还有C3p0、dbcp等--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean>
(3)测试SqlSessionFactory是否创建成功
package test;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName SqlSessionFactoryTest
* @Description 测试SqlSessionFactory是否创建成功
* @Author Jiangnan Cui
* @Date 2022/4/8 16:59
* @Version 1.0
*/
public class SqlSessionFactoryTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("factorybean/spring.xml");
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
System.out.println(sqlSessionFactory);
}
}
测试结果:
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@2d2e5f00
3. SM整合DAO编程步骤
配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili
3.0 整合思路
SM整合编码之DAO层思路分析流程:

SM整合之DAO层编程步骤:

3.1 引入mybatis的依赖jar包
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency>
3.2 引入Spring相关jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.2.RELEASE</version> </dependency>
3.3 mybatis-spring整合jar
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency>
3.4 引入数据库驱动jar
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency>
3.5 建表
CREATE TABLE `t_user` (
`id` varchar(40) NOT NULL,
`name` varchar(40) DEFAULT NULL,
`age` int(3) DEFAULT NULL,
`bir` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.6 编写实体类
package entity;
import java.util.Date;
/**
* @ClassName User
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/8 17:44
* @Version 1.0
*/
public class User {
private String id;
private String name;
private Integer age;
private Date bir;
public User() {
}
public User(String id, String name, Integer age, Date bir) {
this.id = id;
this.name = name;
this.age = age;
this.bir = bir;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBir() {
return bir;
}
public void setBir(Date bir) {
this.bir = bir;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
", bir=" + bir +
'}';
}
}
3.7 书写DAO接口
package dao;
import entity.User;
import java.util.List;
/**
* @ClassName UserDAO
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/8 17:46
* @Version 1.0
*/
public interface UserDAO {
//根据id查询用户信息
User findById(String id);
//查询所有用户信息
List<User> findAll();
//新增用户
void insert(User user);
//根据id修改用户
void update(User user);
//根据id删除用户
void delete(String id);
}
3.8 编写mapper配置文件
<?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为映射的根节点,用来管理DAO接口
namespace指定DAO接口的完整类名,表示mapper配置文件管理哪个DAO接口(包.接口名)
mybatis会依据这个接口动态创建一个实现类去实现这个接口,而这个实现类是一个Mapper对象
-->
<mapper namespace="dao.UserDAO">
<!--
id = "接口中的方法名"
parameterType = "接口中传入方法的参数类型"
resultType = "返回实体类对象:包.类名" 处理结果集 自动封装
注意:sql语句后不要出现";"号
查询:select标签
增加:insert标签
修改:update标签
删除:delete标签
-->
<!--根据id查询用户信息-->
<select id="findById" parameterType="String" resultType="entity.User">
select id,name,age,bir from t_user where id=#{id}
</select>
<!--查询所有用户信息-->
<select id="findAll" resultType="entity.User">
select id,name,age,bir from t_user
</select>
<!--新增用户-->
<insert id="insert" parameterType="entity.User">
insert into t_user values(#{id},#{name},#{age},#{bir});
</insert>
<!--根据id修改用户-->
<update id="update" parameterType="entity.User">
update t_user set name=#{name},age=#{age},bir=#{bir} where id=#{id}
</update>
<!--根据id删除用户-->
<delete id="delete" parameterType="String">
delete from t_user where id=#{id}
</delete>
</mapper>
3.9 编写Spring-myabtis整合配置文件spring.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--创建sqlSessionFactory--> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"> <!--依赖数据源--> <property name="dataSource" ref="dataSource"/> <!--注入mapper配置文件--> <property name="mapperLocations"> <array> <!--依次注册mapper--> <value>classpath:mapper/UserDAOMapper.xml</value> </array> </property> </bean> <!--创建dataSource--> <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!--创建DAO组件类--> <bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="userDAO"> <!--注入SqlSessionFactory--> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> <!--注入创建的DAO接口类型(接口的全限定名:包名.接口名)--> <property name="mapperInterface" value="dao.UserDAO"/> </bean> </beans>
3.10 启动工厂测试
package test;
import dao.UserDAO;
import entity.User;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @ClassName UserDAOTest
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/8 17:55
* @Version 1.0
*/
public class UserDAOTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
//SqlSession sqlSession = sqlSessionFactory.openSession();
//System.out.println(sqlSession);
//UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
//mybatis-spring jar MapperFactoryBean 创建DAO对象一个类
// 1.依赖于SqlSessionFactory 2.依赖创建DAO全限定名
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
List<User> users = userDAO.findAll();
users.forEach(user-> System.out.println("user = " + user));
}
@Test
public void findByIdTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
User user1 = userDAO.findById("1");
System.out.println("user1 = " + user1);
}
@Test
public void findAllTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
List<User> users = userDAO.findAll();
users.forEach(user -> System.out.println("user = " + user));
}
@Test
public void insertTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
String id = UUID.randomUUID().toString();
userDAO.insert(new User(id,"lisi",60,new Date()));
}
@Test
public void updateTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
userDAO.update(new User("4","wangwu",25,new Date()));
}
@Test
public void deleteTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
userDAO.delete("4");
}
}
补充:SM整合编码之DAO细节优化

即:
(1)mapper配置文件注入方式
a. 以数组形式单个注入
<property name="mapperLocations">
<array>
<!--依次注册mapper-->
<value>classpath:mapper/UserDAOMapper.xml</value>
</array>
</property>
b. 通用mapper配置文件扫描注入(推荐使用)
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
+ 补充:起别名
<!--
注入别名相关配置typeAliasesPackage:用来给指定包中所有类起别名
默认的别名:类名/类名首字母小写
-->
<!--指定包-->
<property name="typeAliasesPackage" value="entity"/>
(2)创建DAO组件类
a. 单个注入
<bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="userDAO">
<!--注入SqlSessionFactory-->
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<!--注入创建的DAO接口类型(接口的全限定名:包名.接口名)-->
<property name="mapperInterface" value="dao.UserDAO"/>
</bean>
b. 一次性注入所有(推荐使用)
<!--
一次项目创建项目中所有DAO对象
MapperScannerConfigurer:
默认创建对象在工厂中的唯一标识为接口首字母小写
例如:UserDAO->userDAO Userdao->userdao
OrderDAO->orderDAO Orderdao->orderdao
EmpDAO->empDAO
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入SqlSessionFactory对象-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<!--扫描DAO接口所在包-->
<property name="basePackage" value="dao"/>
</bean>
优化后如下:
<!--创建dataSource-->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--创建sqlSessionFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<!--依赖数据源-->
<property name="dataSource" ref="dataSource"/>
<!--通用mapper配置文件扫描注入,推荐使用-->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<!--
注入别名相关配置typeAliasesPackage:用来给指定包中所有类起别名
默认的别名:类名/类名首字母小写
-->
<!--指定包-->
<property name="typeAliasesPackage" value="entity"/>
</bean>
<!--创建DAO组件类:一次项目创建项目中所有DAO对象-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入SqlSessionFactory对象-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<!--扫描DAO接口所在包-->
<property name="basePackage" value="dao"/>
</bean>
4. SM整合Service编程步骤
配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili
4.1 整合思路
SM整合之Service层事务控制思路分析:

SM整合DAO和Service部分编程步骤:

具体实现:
4.2 开发Service接口
package service;
import entity.User;
import java.util.List;
/**
* @ClassName UserService
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/9 17:13
* @Version 1.0
*/
public interface UserService {
//查询所有用户
List<User> findAll();
//插入用户数据
void insert(User user);
}
4.3 开发Service实现类
package service;
import dao.UserDAO;
import entity.User;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import java.util.List;
import java.util.UUID;
/**
* @ClassName UserServiceImpl
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/9 17:14
* @Version 1.0
*/
public class UserServiceImpl implements UserService{
//Service层需要调用DAO层
private UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
//生成事务管理器
private PlatformTransactionManager platformTransactionManager;
public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
this.platformTransactionManager = platformTransactionManager;
}
//查询所有用户信息
//注意:查询不需要事务管理
@Override
public List<User> findAll() {
return userDAO.findAll();
}
//插入用户信息
//注意:增删改需要事务管理
@Override
public void insert(User user) {
//int i = 1/0;
//创建事务配置对象
TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
//获取事务状态
TransactionStatus status = platformTransactionManager.getTransaction(transactionDefinition);
try {
//处理业务
user.setId(UUID.randomUUID().toString());
//调用业务
//注意:在DAO层进行数据库增删改时,也能操作成功的原因是因为DAO层提供了方法测试的小事务,方便测试DAO
// 当外部存在事务时,小事务自动消失
userDAO.insert(user);
platformTransactionManager.commit(status);
} catch (Exception e) {
e.printStackTrace();
platformTransactionManager.rollback(status);
}
}
}
4.4 编写spring.xml
<!--配置数据源事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!--注入数据源对象 DataSource-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--管理Service组件-->
<bean class="service.UserServiceImpl" id="userService">
<!--Service组件需要DAO组件,需要注入-->
<property name="userDAO" ref="userDAO"/>
<!--需要在Service进行事务管理-->
<property name="platformTransactionManager" ref="transactionManager"/>
</bean>
4.5 启动工厂测试
package test;
import entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;
import java.util.Date;
/**
* @ClassName UserServiceTest
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/9 17:41
* @Version 1.0
*/
public class UserServiceTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
//System.out.println(userService.getClass());
userService.insert(new User(null,"小超超",36,new Date()));
userService.findAll().forEach(user -> System.out.println("user = " + user));
}
}
4.6 小结
配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

5. SM整合Service层事务优化思路分析
配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili
spring中的两种事务管理方式:

spring中声明式事务分析思路:

具体实现如下:
5.1 在spring-mybatis.xml文件中添加配置
<!--管理Service组件-->
<bean class="service.UserServiceImpl" id="userService">
<!--Service组件需要DAO组件,需要注入-->
<property name="userDAO" ref="userDAO"/>
<!--Service组件原有的事务管理移出-->
</bean>
<!--创建数据源事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源对象 DataSource-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务属性
tx:advice标签
id: 基于事务管理器创建的环绕通知对象在工厂中唯一标识
作用:
1.根据指定的事务管理器在工厂中创建一个事务的环绕通知对象
2.对业务层方法进行细粒度事务控制
transactionManager:指定事务管理器是谁
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--事务细粒度配置-->
<tx:attributes>
<!--*表示任意,此处针对增删改方法添加事务管理-->
<tx:method name="insert*"/>
<tx:method name="delete*"/>
<tx:method name="update*"/>
</tx:attributes>
</tx:advice>
<!--配置事务切面-->
<aop:config>
<!--指定切点-->
<aop:pointcut id="pc" expression="within(service.*ServiceImpl)"/>
<!--绑定切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>
5.2 配置图示

5.3 优化UserServiceImpl实现类
package service;
import dao.UserDAO;
import entity.User;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import java.util.List;
import java.util.UUID;
/**
* @ClassName UserServiceImpl
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/9 17:14
* @Version 1.0
*/
public class UserServiceImpl implements UserService{
//Service层需要调用DAO层
private UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
/**
* @MethodName findAll
* @Description 查询所有用户信息,查询不需要事务管理
* @return: java.util.List<entity.User>
* @Author Jiangnan Cui
* @Date 2022/4/11 21:31
*/
@Override
public List<User> findAll() {
return userDAO.findAll();
}
/**
* @MethodName insert
* @Description 插入用户信息,需要事务管理
* @param: user
* @Author Jiangnan Cui
* @Date 2022/4/11 21:29
*/
@Override
public void insert(User user) {
//处理业务
user.setId(UUID.randomUUID().toString());
//调用业务
//注意:在DAO层进行数据库增删改时,也能操作成功的原因是因为DAO层提供了方法测试的小事务,方便测试DAO
// 当外部存在事务时,小事务自动消失
userDAO.insert(user);
//int i = 1/0;//测试异常
}
}
5.4 启动测试
package test;
import entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;
import java.util.Date;
/**
* @ClassName UserServiceTest
* @Description TODO
* @Author Jiangnan Cui
* @Date 2022/4/9 17:41
* @Version 1.0
*/
public class UserServiceTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
//System.out.println(userService.getClass());
//insert
userService.insert(new User(null,"小胖墩",3,new Date()));
//findAll
userService.findAll().forEach(user -> System.out.println("user = " + user));
}
}
测试结果:
(1)不注释int i = 1/0;数据插入不成功
Exception in thread "main" java.lang.ArithmeticException: / by zero
at service.UserServiceImpl.insert(UserServiceImpl.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:280)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy9.insert(Unknown Source)
at test.UserServiceTest.main(UserServiceTest.java:23)
(2)注释掉int i = 1/0;数据插入成功
user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022}
user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022}
user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022}
user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022}
user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022}
user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022}
user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022}
user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022}
user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022}
user = User{id='9', name='小崔', age=25, bir=Sun Apr 10 09:55:52 CST 2022}
user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022}
5.5 SM最终开发步骤
配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili

5.6 SM中添加log4j日志
配套视频:【编程不良人】快速入门Spring,SpringBoot、SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili
pom.xml中添加依赖:
<!--log4j依赖--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency> </dependencies>
在src-main-resources下新建log4j.properties:
## 根日志
## 日志级别
log4j.rootLogger=ERROR,stdout
## 输出位置
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
## 布局
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
## 格式
log4j.appender.stdout.layout.conversionPattern=[%p] %d{yyyy-MM-dd} %m%n
## 子日志
## 日志级别
log4j.logger.dao=DEBUG
## 监听spring框架的日志级别
log4j.logger.org.springframework=ERROR
测试结果:
[DEBUG] 2022-04-12 ==> Preparing: insert into t_user values(?,?,?,?);
[DEBUG] 2022-04-12 ==> Parameters: 8a3e8ab8-5abc-44e1-9aec-31f3978d97f2(String), 小胖墩(String), 3(Integer), 2022-04-12 10:23:32.991(Timestamp)
[DEBUG] 2022-04-12 <== Updates: 1
[DEBUG] 2022-04-12 ==> Preparing: select id,name,age,bir from t_user
[DEBUG] 2022-04-12 ==> Parameters:
[DEBUG] 2022-04-12 <== Total: 14
user = User{id='1', name='张三', age=10, bir=Fri Apr 01 00:00:00 CST 2022}
user = User{id='2', name='李四', age=20, bir=Sat Apr 02 00:00:00 CST 2022}
user = User{id='2f278828-6422-432d-ab1b-a727b33c23bc', name='小胖墩', age=3, bir=Mon Apr 11 21:43:57 CST 2022}
user = User{id='3', name='王五', age=30, bir=Sun Apr 03 00:00:00 CST 2022}
user = User{id='4', name='灰太狼', age=60, bir=Sun Apr 10 09:56:17 CST 2022}
user = User{id='5', name='小超超', age=36, bir=Sun Apr 10 09:55:41 CST 2022}
user = User{id='586a5f71-836c-4171-a038-4620fe0f9354', name='葫芦娃', age=5, bir=Tue Apr 12 09:45:17 CST 2022}
user = User{id='6', name='小呆呆', age=60, bir=Sun Apr 10 09:55:43 CST 2022}
user = User{id='7', name='小超超', age=36, bir=Sun Apr 10 09:55:44 CST 2022}
user = User{id='8', name='胖嘟嘟', age=50, bir=Sun Apr 10 09:55:39 CST 2022}
user = User{id='8a3e8ab8-5abc-44e1-9aec-31f3978d97f2', name='小胖墩', age=3, bir=Tue Apr 12 10:23:33 CST 2022}
user = User{id='9', name='小崔', age=25, bir=Sun Apr 10 09:55:52 CST 2022}
user = User{id='cd280176-68b2-4ceb-b781-ba2f5e1fbeff', name='小胖墩', age=3, bir=Tue Apr 12 10:21:18 CST 2022}
user = User{id='e3863fd3-173c-46f4-a753-c72f7c92ad56', name='小猫咪', age=3, bir=Mon Apr 11 21:36:31 CST 2022}
注:ERROR前还有OFF,一般不用。
Spring与Mybatis整合实践及事务管理
本文详细介绍了如何在Maven项目中创建复杂对象,如接口和抽象类的实例,通过FactoryBean实现。接着,讲解了Spring和Mybatis的整合思路,包括Spring管理SqlSessionFactory、数据源配置、Mapper配置、DAO组件创建等内容。此外,还展示了Service层的事务控制和优化,以及如何通过log4j添加日志。最后,文章提到了SM整合的DAO和Service编程步骤,以及日志管理的重要性。
1万+

被折叠的 条评论
为什么被折叠?



