MyBatis
一、MyBatis的简介
1.什么是MyBatis
一个半自动的ORM(对象关系映射)持久层框架
2.如何搭建MyBatis项目
1.创建maven项目
2.需要到maven仓库中找到对应的依赖文件
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!--这是做单元测试的jar包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<!--pageHelper分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.4</version>
</dependency>
</dependencies>
3.创建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">
<!--配置-->
<configuration>
<!--配置SQL日志的输出-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!--当我们ResultMap中没有写的东西不会自动绑定的时候,就需要配置MyBatis的行为映射了-->
<setting name="autoMappingBehavior" value="FULL"></setting>
</settings>
<typeAliases>
<!--package 包-->
<package name="entity"></package>
</typeAliases>
<!-- 配置分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
<!--运行环境 default默认,引用-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--驱动-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!--路径-->
<property name="url" value="jdbc:mysql://localhost:3306/smbms?characterEncoding=UTF-8&useUnicode=true&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--对应SQL映射文件,有多少个xml文件就要配置多少次-->
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
4.创建项目的包
- entity
- mapper
- util
- test
5.写接口
package mapper;
import entity.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface UserMapper {
/**
* 查询所有用户
*/
List<User> findUsers();
}
6.写接口对应的SQL映射文件
UserMapper.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="mapper.UserMapper">
<select id="findUsers" resultType="entity.User">
select * from smbms_user
</select>
</mapper>
7.工具类
package 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.IOException;
import java.io.InputStream;
public class MyBatisUtil {
public static SqlSession getSqlSession(){
//通过流的方式读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
//通过工人获取工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//工厂获取操作sql的对象
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
public static void closeSqlSession(SqlSession sqlSession){
if (sqlSession!=null){
sqlSession.close();
}
}
}
8.编写测试类进行测试
package test;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import entity.User;
import mapper.UserMapper;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import utils.MyBatisUtil;
import java.util.List;
public class UserTest {
@Test
public void findAll(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.findUsers();
users.forEach(user->{
System.out.println(user.toString());
});
MyBatisUtil.closeSqlSession(sqlSession);
}
@Test
public void testPage(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//1.开始分页
PageHelper.startPage(2,4);
//2.查询所有
List<User> userList = userMapper.findUsers();
//3.封装分页对象
PageInfo<User> pageInfo = new PageInfo<>(userList);
//4.取数据
List<User> users = pageInfo.getList();
users.forEach(user->{
System.out.println(user.toString());
});
MyBatisUtil.closeSqlSession(sqlSession);
}
}
MyBatis中三个重要的对象生命周期以及作用域
SqlSessionFactoryBuilder: 建造者
SqlSessionFactory:工厂
SqlSession:会话
SQL映射文件
模糊查询如何实现:
select * from user where name like concat('%',#{name},'%')
多参数入参的方式:
1.通过@Param取别名的方式可以实现
List<User> selAll(@Param("userName") String userName,@Param("userRole") String userRole);
select * from user where userName like concat('%',#{userName},'%') and userRole = #{userRole}
2.封装成对象
List selAll(User user)
//主要User对象中的属性(字段)叫什么
select * from user where userName like concat(’%’,#{userName},’%’) and userRole = #{userRole}
3.封装成Map进行传参
List selAll(Map<String,Object> map)
//主要User对象中的属性(字段)叫什么
select * from user where userName like concat(’%’,#{map的key},’%’) and userRole = #{map的key}
赋值如何实现
map.put(“name”,“孙”);
update insert delete
4.当数据库字段和实体类的字段不一致的时候如何解决
多表联查如何实现
1.在User表中添加一个字段 roleName,在SQL映射文件中取别名
在User实体类中添加了一个roleName的一个字段,在通过SQL查询的返回的字段名称也叫roleName
2.使用ResultMap解决字段和属性不一致的问题
一对一和一对多 分页查询
实现方式:
User----->Role
那就在User类中添加一个Role的字段,刚好构成用户和角色一对一的关系
返回值那就不能直接写ResultType,因为Role不属于User表的字段
只能使用ResultMap
用户跟地址的关系就是一对多,供应商跟订单的关系
分页查询:
1.开始分页
PageHelper.startPage(页码,每页条数);
2.查询数据
List userList = userMapper.selAll();
3.封装成分页对象
PageInfo pageInfo = new PageInfo(userList);
4.取值
List users = pageInfo.getList();
pageInfo.getTotal()
pageInfo.getPages()
pageInfo.hasNextPage()…
动态SQL标签
if
<!--出现的问题: 要么多个where 要么多个and-->
<select id="findUserByNameOrRole" resultType="entity.User">
SELECT
*
FROM
`smbms_user`
<if test="userName != null and userName != ''">
where userName LIKE concat( '%', #{userName}, '%' )
</if>
<if test="userRole != null">
AND userRole = #{userRole}
</if>
</select>
where+if
<!--
where的作用
1.根据条件自动拼接where,如果两个if都为空,则不会拼接where,但是
只要有一个不为空则会拼接一个where
2.会自动的删除and
where的用法:直接将if放入where就OK了,但是要记得加and
-->
<select id="findUserByNameOrRoleByUseWhere" resultType="entity.User">
SELECT
*
FROM
`smbms_user`
<where>
<if test="userName != null and userName != ''">
AND userName LIKE concat( '%', #{userName}, '%' )
</if>
<if test="userRole != null">
AND userRole = #{userRole}
</if>
</where>
</select>
set
<!--
出现的问题:没有修改的内容都会变成null值
-->
<update id="updateUserByIf">
UPDATE `smbms`.`smbms_user` SET
<if test="username != null and username != ''">
userName = #{username},
</if>
<if test="usercode != null and usercode != ''">
userCode = #{usercode},
</if>
<if test="userpassword != null and userpassword != ''">
userPassword = #{userpassword}
</if>
where id = #{id}
</update>
set+if
<!--
set的用法和where的用法差不多,也是把if包起来,并且作用都是一样的
1.自动拼接set
2.自动剔除,
-->
<update id="updateUserByIfAndSet">
UPDATE `smbms`.`smbms_user`
<set>
<if test="username != null and username != ''">
userName = #{username},
</if>
<if test="usercode != null and usercode != ''">
userCode = #{usercode},
</if>
<if test="userpassword != null and userpassword != ''">
userPassword = #{userpassword},
</if>
</set>
where id = #{id}
</update>
trim
- 代替where+if
<select id="findUserByNameOrRoleByUseTrim" resultType="entity.User">
SELECT
*
FROM
`smbms_user`
<!--trim前面是前缀 trim后面是后缀 -->
<!--
prefix="前缀" suffix="后缀"
prefixOverrides="忽略前缀" suffixOverrides="忽略后缀"
-->
<trim prefix="where" prefixOverrides="and">
<if test="userName != null and userName != ''">
AND userName LIKE concat( '%', #{userName}, '%' )
</if>
<if test="userRole != null">
AND userRole = #{userRole}
</if>
</trim>
</select>
- 代替set+if
<update id="updateUserByTrim">
UPDATE `smbms`.`smbms_user`
<trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
<if test="username != null and username != ''">
userName = #{username},
</if>
<if test="usercode != null and usercode != ''">
userCode = #{usercode},
</if>
<if test="userpassword != null and userpassword != ''">
userPassword = #{userpassword},
</if>
</trim>
</update>
foreach
- 批量删除
<delete id="deleteUsers">
delete from smbms_user where id in
<foreach collection="array" open="(" item="id" separator="," close=")">
#{id}
</foreach>
</delete>
- 批量查询
<select id="findByCodeAndPid" resultMap="BaseResultMap">
SELECT
*
FROM
`smbms_bill`
WHERE
billCode LIKE concat( '%', #{billCode}, '%' )
AND providerId IN
<!--collection有三个取值 array表示数组 list表示集合 map表示map集合-->
<!--
open 是以xx开头 (
item是循环出来的每一个元素 循环数组pids得到的值pid
separator 以XX进行分割 ,
close 以XX结束/关闭
(6,7,13)
-->
<foreach collection="array" open="(" item="pid" separator="," close=")">
#{pid}
</foreach>
</select>
choose
<select id="findByChoose" resultType="entity.User">
select * from smbms_user
<trim prefix="where" prefixOverrides="and | or">
<choose>
<!--if else-if else-->
<when test="userCode != null and userCode != ''">
and userCode = #{userCode}
</when>
<when test="userName != null and userName != ''">
and userName = #{userName}
</when>
<otherwise>
and userRole = #{userRole}
</otherwise>
</choose>
</trim>
</select>