1:介绍
MyBatis:
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
Spring:
Spring是一个开源框架,它是为了解决企业应用开发的复杂性而创建的。Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架。
2:Spring对MyBatis提供那些支持
MyBatis需求:
- DataSource数据源
- SqlSessionFactory对象
- Mapper接口对象
- TransactionManager对象-事务管理
Spring可以为MyBatis提供这些对象的创建并交给IOC管理。
Spring可以为事务管理提供切面类,完成增删改查的事务管理。
3:整合环境
- Maven工程
- JDK1.8
- MySql数据库
- MyBatis3.5.7
- Spring5.2.13
- ehcache缓存
- 分页插件
- Druid数据库连接池
- slf4j日志
4:添加工程依赖
- MySql驱动包
- MyBatis核心包
- SpringContext,SpringAOP,SpringJDBC包
- mybatis-spring整合包
- Druid数据库连接池
- MyBatis分页插件
- mybatis-ehcache整合包
- slf4j日志门面具体实现
- junit单元测试包
<dependencies>
<!--MyBatis依赖-->
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--Spring依赖-->
<!--SpringContext-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<!--SpringAOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<!--SpringJDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<!--MyBatis提供的兼容Spring的补丁,MyBatis-Spring整合包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--druid数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
<!--MyBatis的ehcache的整合包-->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<!--slf4j日志门面的具体实现-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
5:数据库表
6:项目目录
7:配置MyBatis
7.1:MyBatis核心配置文件
mybatis-config:
<?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="mapUnderscoreToCamelCase" value="true"/>
<!--开启懒加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭激情加载-->
<setting name="aggressiveLazyLoading" value="false"/>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
7.2:MyBatis数据源配置
7.2.1:Druid数据库连接配置
druid.properties:
druid.driver=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/数据库名?characterEncoding=UTF-8
druid.username=root
druid.password=root
#初始化连接数
druid.pool.init=1
#最小连接数
druid.pool.minIdle=3
#最大连接数
druid.pool.maxActive=20
#最长等待连接时间
druid.pool.timeout=30000
7.2.2:Spring配置文件引入druid.properties文件
applicationContext:
<!--引入资源文件druid.properties-->
<context:property-placeholder location="classpath:/druid.properties"/>
7.2.3:Spring配置文件配置数据源
将原本由mybatis配置的数据源,放到spring配置,交给IOC容器管理。
重点: Druid数据库连接池的参数driver是一个对象,并不是字符串,所以需要声明一个Driver对象,也交给IOC,并在配置数据源时引用。
<bean id="driver" class="com.mysql.jdbc.Driver"/>
<property name="driver" ref="driver"/>
或者也可以使用driverClassName:
<property name="driverClassName"value="${druid.driver}"/>
applicationContext:
<bean id="driver" class="com.mysql.jdbc.Driver"/>
<!--借助Spring的IOC创建druid数据库连接池,配置数据源(只能通过xml形式)-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--drier需要对象-->
<property name="driver" ref="driver"/>
<!--<property name="driverClassName"value="${druid.driver}"/>-->
<property name="url" value="${druid.url}"/>
<property name="username" value="${druid.username}"/>
<property name="password" value="${druid.password}"/>
<property name="initialSize" value="${druid.pool.init}"/>
<property name="minIdle" value="${druid.pool.minIdle}"/>
<property name="maxActive" value="${druid.pool.maxActive}"/>
<property name="maxWait" value="${druid.pool.timeout}"/>
</bean>
7.3:SqlSessionFactory配置
MyBatis创建SqlSessionFactory时,传入的参数时mybatis的核心配置文件。文件包含了各种配置,我们将SqlSessionFactory交给SpringIOC管理,可以配置数据源,mapper文件,实体类别名,甚至还有mybatis的核心配置文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xx8JWTpQ-1647158021815)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220313151641798.png)]
7.3.1:实体类对象
//因为使用MyBatis二级缓存所以实现序列化接口
public class User implements Serializable {
private Integer id;
private String userName;
private String passWord;
private Integer age;
private String sex;
private String email;
public User() {
}
public User(Integer id, String userName, String passWord, Integer age, String sex, String email) {
this.id = id;
this.userName = userName;
this.passWord = passWord;
this.age = age;
this.sex = sex;
this.email = email;
}
//提供get和set已经toString方法
}
7.3.2:Dao层
public interface UserDao {
List<User> queryAllUser();
int insertUser(User user);
}
7.3.3:Mapper.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="com.lk.dao.UserDao">
<!--使用ehcache二级缓存-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="userName" column="username"/>
<result property="passWord" column="password"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
<result property="email" column="email"/>
</resultMap>
<!--查询所有User,public List<User> queryAllUser();-->
<select id="queryAllUser" resultMap="userMap">
select * from t_user
</select>
<!--添加用户 int insertUser(User user);-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{userName},#{passWord},#{age},#{sex},#{email})
</insert>
</mapper>
7.3.4:Spring配置文件中配置SqlSessionFactory
applicationContext:
<!--通过spring完成mybatis的SqlSessionFactory的创建-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--加载数据源-->
<property name="dataSource" ref="druidDataSource"/>
<!--加载mapper.xml-->
<property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<!--实体类别名-->
<property name="typeAliasesPackage" value="com.lk.pojo"/>
<!--加载mybatis-config的主配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
7.4:Mapper管理
MyBatis如何获取Dao层接口实例?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LolGWuz0-1647158021816)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220313152933037.png)]
applicationContext:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--获取sqlSessionFactory对象-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--扫描Dao包,获得接口的对象-->
<property name="basePackage" value="com.lk.dao"/>
</bean>
8:SpringAOP管理事务
8.1:XML配置
1:配置Spring提供的事务管理类
2:通过Spring.jdbc提供的tx标签,声明事务管理策略
3:面向切面编程,AOP管理事务
<!--1:配置Spring提供的事务管理类,交给IOC管理-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--2:通过Spring.jdbc提供的tx标签,声明事务管理策略-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--增删改 一般使用REPEATABLE_READ(可重复读)和REQUIRED(有则加入没有则创建)-->
<tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<!--查询 一般使用REPEATABLE_READ(可重复读)和SUPPORTS(有则加入没有则非事务)-->
<tx:method name="query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!--3:面向切面编程-->
<aop:config>
<!--配置切入点-->
<!--一个业务才是一个事务-->
<aop:pointcut id="crud" expression="execution(* com.lk.service.*.*(..))"/>
<!--配置通知-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="crud"></aop:advisor>
</aop:config>
8.2:注解配置
1:配置Spring提供的事务管理类,交给IOC管理
2:声明注解驱动事务管理
<!--开启注解驱动-->
<context:annotation-config/>
<!--声明扫描的包-->
<context:component-scan base-package="com"/>
<!--1:配置Spring提供的事务管理类,交给IOC管理-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--2:声明注解驱动事务管理-->
<tx:annotation-driven transaction-manager="transactionManager"/>
3:在Service层配置事务策略
Service层接口:
public interface UserService {
public List<User> queryListUsers();
public int insertUser(User user);
}
Service层实现类:
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserDao userDao;
@Override
//默认可重复读 @Transactional声明事务管理和策略
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.SUPPORTS )
public List<User> queryListUsers() {
List<User> users = userDao.queryAllUser();
return users;
}
@Override
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
public int insertUser(User user) {
int i = userDao.insertUser(user);
return i;
}
}
9:测试
因为通过AOP进行事务管理,且Service层分为接口和实现类,AOP底层是动态代理,因为有接口所以是JDK动态代理,返回的是接口的实现类,但需要用接口接收。
UserService userServiceImpl = (UserService) context.getBean("userServiceImpl");
@Test
public void listUsers() {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userServiceImpl = (UserService) context.getBean("userServiceImpl");
//分页查询 2个结果一页,找第二页数据
PageHelper.startPage(2,2);
List<User> users = userServiceImpl.queryListUsers();
users.forEach(u-> System.out.println(u));
}
10:slf4j配置和ehcache配置
logback.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 指定日志输出的位置 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志输出的格式 -->
<!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n
</pattern>
</encoder>
</appender>
<!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
<!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
<root level="DEBUG">
<!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
<appender-ref ref="STDOUT"/>
</root>
<!-- 根据特殊需求指定局部日志级别 包名-->
<logger name="com.lk.dao" level="DEBUG"/>
</configuration>
ehcache.xml:xsd格式报错不用管
<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path=""/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>