项目已托管到GitHub,大家可以去GitHub查看下载!并搜索关注微信公众号 码出Offer 领取各种学习资料!
一、框架概述
1.1 什么是框架?
1.2 什么是ORM框架?
1.3 使用JDBC完成ORM的缺点
二、MyBatis概述
2.1 什么是MyBatis
2.2 官网
2.3 使用
三、搭建MyBatis项目
3.1 创建一个Maven项目
3.2 导入MyBatis依赖
<!--MyBatis核心依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--日志依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--MySql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
3.3 创建MyBatis配置文件
<?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">
<!--MyBatis配置-->
<configuration>
<!--JDBC环境配置、选中默认环境-->
<environments default="MySqlDB">
<!--MySql数据库环境配置-->
<environment id="MySqlDB">
<!--事务管理-->
<transactionManager type="JDBC"/>
<!--连接池-->
<dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- &转义& -->
<property name="url" value="jdbc:mysql://localhost:3306/x?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--Mapper注册-->
<mappers>
<!--注册Mapper文件的所在位置-->
<mapper resource="xxxMapper.xml"/>
</mappers>
</configuration>
3.4 建表
create table tb_user
(
id int auto_increment
primary key,
username varchar(30) null,
password varchar(30) null,
gender char null,
birth date null
) charset = utf8;
3.5 书写实体类代码
package com.mylifes1110.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private Boolean gender;
private Date birth;
}
3.6 定义Dao层接口
package com.mylifes1110.dao;
import com.mylifes1110.bean.User;
public interface UserDao {
User selectUserById(int id);
}
3.7 创建并编写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">
<!--namespace:所需实现的接口全限定名-->
<mapper namespace="com.mylifes1110.dao.UserDao">
<!--id:所需重写的接口抽象方法;resultType:查询后所需返回的对象类型-->
<select id="selectUserById" resultType="com.mylifes1110.bean.User">
<!--select标签是查询标签,里面包裹着查询的sql语句,其中id = #{arg0}是id = ?的意思-->
<!--#{arg0}是指id等于方法中第一个形参,也就是id-->
select id, username, password, gender, birth from tb_user where id = #{arg0}
</select>
</mapper>
3.7 注册Mapper
<!--Mapper注册-->
<mappers>
<!--注册Mapper文件的所在位置-->
<mapper resource="xxxMapper.xml"/>
</mappers>
3.8 测试方式1(常用)
package com.mylifes1110.dao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class UserMapperTest {
@Test
public void selectUserByIdTest() throws IOException {
// 获得读取MyBatis核心配置文件的流对象
InputStream input = Resources.getResourceAsStream("mybatis-config.xml");
// 根据流对象构建SqlSession连接对象的工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(input);
// 通过工厂获得连接对象sqlSession
SqlSession sqlSession = factory.openSession();
// 通过连接对象获得接口实现类对象
UserDao userDaoImpl = sqlSession.getMapper(UserDao.class);
// 打印结果
System.out.println(userDaoImpl.selectUserById(1));
}
}
3.9 测试方式2(了解)
package com.mylifes1110.dao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class UserMapperTest {
@Test
public void selectUserByIdTest2() throws IOException {
// 获得读取MyBatis核心配置文件的流对象
InputStream input = Resources.getResourceAsStream("mybatis-config.xml");
// 根据流对象构建SqlSession连接对象的工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(input);
// 通过工厂获得连接对象sqlSession
SqlSession sqlSession = factory.openSession();
// 通过连接对象直接调用接口中的方法
Object o = sqlSession.selectOne("com.mylifes1110.dao.UserDao.selectUserById", 1);
// 打印结果
System.out.println(o);
}
}
四、MyBatis框架使用细节
4.1 解决mapper.xml存放在resources以外路径中的读取问题
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include><!-- 新添加 */代表1级目录 **/代表多级目录 -->
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include><!-- 新添加 */代表1级目录 **/代表多级目录 -->
<include>**/*.properties</include><!--添加properties文件-->
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
4.2 解决JDBC写死问题
创建jdbc.properties配置文件
#jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/temp?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
修改mybatis-config.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">
<!--MyBatis配置-->
<configuration>
<properties resource="jdbc.properties" />
<!--JDBC环境配置、选中默认环境-->
<environments default="MySqlDB">
<!--MySql数据库环境配置-->
<environment id="MySqlDB">
<!--事务管理-->
<transactionManager type="JDBC"/>
<!--连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<!-- &转义& -->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--Mapper注册-->
<mappers>
<!--注册Mapper文件的所在位置-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
4.3 类型别名
<!--定义别名二选一-->
<typeAliases>
<!--定义类的别名-->
<typeAlias type="com.mylifes1110.bean.User" alias="User" />
<!--自动扫描包,将原类名作为别名-->
<package name="com.mylifes1110.bean" />
</typeAliases>
4.4 使用log4j日志依赖
向pom.xml文件中添加log4j依赖
<!-- log4j日志依赖 https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
创建并配置log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.com.mylifes1110.dao=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
日志信息
4.5 注册Mapper
4.5.1 扫描包注册Mapper
<!--扫描包方式Mapper注册-->
<mappers>
<!--dao层路径-->
<package name="com.mylifes1110.dao"/>
</mappers>
4.5.2 单一注册Mapper路径问题
<!--Mapper注册-->
<mappers>
<!--注册Mapper文件的所在位置-->
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
五、MyBatis的CURD操作
5.1 参数绑定
5.1.1 序号参数绑定
// Dao层接口
User selectUserByUserNameAndPassword(String username, String password);
// Mapper.xml
<select id="selectUserByUserNameAndPassword1" resultType="User">
SELECT * FROM t_user
WHERE username = #{arg0} and password = #{arg1}
</select>
5.1.2 注解参数绑定
// Dao层接口
User selectUserByUserNameAndPassword(@Param("username") String username, @Param("password")String password);
// Mapper.xml
<select id="selectUserByUserNameAndPassword2" resultType="User">
SELECT * FROM t_user
WHERE username = #{username} and password = #{password}
</select>
5.1.3 Map参数绑定
// Dao层接口
User selectUserByUserNameAndPassword(String username, String password);
// 测试类创建Map集合,封装数据
Map<String, Object> map = new HashMap<>();
// 自定义key,绑定参数
map.put("username", "root");
map.put("password", "123456");
User user = userDao.selectUserByUserNameAndPassword(map);
// Mapper.xml
<select id="selectUserByUserNameAndPassword3" resultType="User">
SELECT * FROM t_user
WHERE username = #{username} and password = #{password} <!-- 通过key获得value -->
</select>
5.1.4 对象参数绑定
// Dao层接口
User selectUserByUserNameAndPassword(User user);
// Mapper.xml
<select id="selectUserByUserNameAndPassword4" resultType="User">
SELECT * FROM t_user
WHERE username = #{username} and password = #{password} <!-- 对象中取出的字段值 -->
</select>
5.2 查询操作
5.2.1 查询标签
5.2.2 普通查询
// Dao层接口
User selectUserByUserNameAndPassword(@Param("username") String username, @Param("password")String password);
// Mapper.xml
<select id="selectUserByUserNameAndPassword2" resultType="User">
SELECT * FROM t_user
WHERE username = #{username} and password = #{password}
</select>
5.2.3 查询总数据条数
// Dao层接口
long selectUserCount();
// Mapper.xml
<select id="selectUserCount" resultType="java.lang.Long">
select count(1) from tb_user
</select>
// 测试类
@Test
public void selectUserCount() throws IOException {
InputStream input = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(input);
SqlSession sqlSession = factory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
System.out.println(userDao.selectUserCount());
}
5.2.4 模糊查询
// Dao层接口
List<User> selectUserListByUsername1(@Param("username") String username);
// Mapper.xml
<select id="selectUserListByUsername1" resultType="com.mylifes1110.bean.User">
select id, username, password, gender, birth
from tb_user
where username like concat('%',#{username},'%')
</select>
// 查询包含Z的username
@Test
public void selectUserListByUsername1() throws IOException {
InputStream input = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(input);
SqlSession sqlSession = factory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
System.out.println(userDao.selectUserListByUsername1("Z"));
}
5.3 删除操作
5.3.1 删除标签
5.3.2 删除
// Dao层接口
int deleteUserById(@Param("id") int id);
// Mapper.xml
<delete id="deleteUserById">
delete from tb_user where id = #{id}
</delete>
5.4 修改操作
5.4.1 修改标签
5.4.2 修改
// Dao层接口
int updateUserById(User user);
// Mapper.xml
<update id="updateUserById">
update tb_user set
username = #{username}, password = #{password}, gender = #{gender}, birth = #{birth}
where id = #{id}
</update>
5.5 新增操作
5.5.1 新增标签
5.5.2 新增
// Dao层接口
int insertUser(User user);
// Mapper.xml
<insert id="insertUser">
insert into tb_user
(username, password, gender, birth)
values
(#{username}, #{password}, #{gender}, #{birth})
</insert>
5.6 主键回填操作
5.6.1 什么是主键回填?
5.6.2 主键回填标签
5.6.3 通过last_insert_id()查询主键(int)
// 表使用的是User表
// Dao层接口
int insertUser(User user);
// Mapper.xml
<insert id="insertUser">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()<!--适用于整数类型自增的主键-->
</selectKey>
insert into tb_user
(username, password, gender, birth)
values
(#{username}, #{password}, #{gender}, #{birth})
</insert>
// 测试类
@Test
public void insertOrder() {
OrderDao orderDao = MyBatisUtils.getMapper(OrderDao.class);
Order order = new Order();
order.setMoney(11.1D);
order.setUserId(2);
System.out.println(orderDao.insertOrder(order));
System.out.println(order.getId());
MyBatisUtils.commit();
}
5.6.4 通过uuid()查询主键(String)
// 创建订单表
create table tb_order
(
id varchar(32) not null
primary key,
money double null,
user_id int null
) charset = utf8;
// Dao层接口
int insertOrder(Order order);
// Mapper.xml
<insert id="insertOrder" parameterType="com.mylifes1110.bean.Order">
<selectKey keyProperty="id" resultType="string" order="BEFORE">
select replace(UUID(), '-', '')
</selectKey>
insert into tb_order
(id, money, user_Id)
values
(#{id}, #{money}, #{userId})
</insert>
六、封装工具类
6.1 封装工具类分析
6.2 MyBatis工具类
package com.mylifes1110.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
/**
* @ClassName MyBatisUtils
* @Description MyBatis工具类
* @Author Ziph
* @Date 2020/7/11
* @Since 1.8
* @Version 1.0
*/
public class MyBatisUtils {
// 获得SqlSession工厂
private static SqlSessionFactory factory;
// 创建ThreadLocal绑定当前线程中的SqlSession对象
private static final ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();
static {
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(is);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获得连接(从tl中获得当前线程SqlSession)
private static SqlSession openSession(){
SqlSession session = tl.get();
if(session == null){
session = factory.openSession();
tl.set(session);
}
return session;
}
// 释放连接(释放当前线程中的SqlSession)
public static void closeSession(){
SqlSession session = tl.get();
session.close();
tl.remove();
}
// 提交事务(提交当前线程中的SqlSession所管理的事务)
public static void commit(){
SqlSession session = openSession();
session.commit();
closeSession();
}
// 回滚事务(回滚当前线程中的SqlSession所管理的事务)
public static void rollback(){
SqlSession session = openSession();
session.rollback();
closeSession();
}
// 获得接口实现类对象
public static <T extends Object> T getMapper(Class<T> clazz){
SqlSession session = openSession();
return session.getMapper(clazz);
}
}