MyBatis
MyBatis
MyBatis是一款优秀的持久层的框架,用于简化JDBC的开发(JDBC是在java语言使用SQL语言,来调用,修改,添加数据库数据的)
持久层:负责将数据保存到数据库的那一层代码
javaEE三层框架:表现层,业务层,持久层
框架:就是一个半成品的软件,是一套可重用,通用的,软件基础代码模型
在框架的基础上构建软件编写更加高效,规范,可扩张
MyBatis快速入门
查询user表中所有数据
- 创建user表,添加数据
- 创建模块,导入坐标
- 编写MyBatis核心配置文件 --->替换连接信息,解决硬编码问题
- 编写SQL映射文件 --->统一管理sql语句,解决硬编码问题
- 编码
- 定义POJO类
- 加载核心配置文件,获取SqlSessionFactory对象
- 获取SqlSession对象,执行SQL语句
- 释放资源
ait+鼠标左键可以整列编辑
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>com.example</groupId>
<artifactId>mybatis-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>22</maven.compiler.source>
<maven.compiler.target>22</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!--junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!--添加logback-classic依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--添加logback-core依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>mysql-repo</id>
<url>https://repo.mysql.com/</url>
</repository>
</repositories>
</project>
在pom.xml中加入
<dependencies>
<!--mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!--junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!--添加logback-classic依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--添加logback-core依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>mysql-repo</id>
<url>https://repo.mysql.com/</url>
</repository>
</repositories>
在main的resources中加入logback.xml,mybatis-config.xml和UserMapper.xml
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- console表示当前日志信息是可以输出到控制台的-->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>【%level】 %cyan(【%thread】) %boldGreen(%logger{15}) - %msg %n</pattern>
</encoder>
</appender>
<logger name="com.Carter_x" level="DEBUG" additivity="false">
<appender-ref ref="Console"/>
</logger>
</configuration>
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>
<typeAliases>
<package name="com.pugo"/>
</typeAliases>
//起别名之后涉及到USer的实体类是可以直接写user并且不用区分大小写
<!--
environments:配置数据库连接环境信息的,可以配置多个environment,通过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://127.0.0.1:3306/blog"/>
//数据库,端口,
<property name="username" value="root"/>
//账户名
<property name="password" value="ROOT"/>
//密码
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/blog"/>
<property name="username" value="root"/>
<property name="password" value="ROOT"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--包扫描的方式加载映射文件 -->
<package name="com.mapper"/>
</mappers>
</configuration>
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">
<!--
namepace:名称空间
-->
<mapper namespace="com.mapper.UserMapper">
<select id="selectAll" resultType="com.ruming.USer">
select * from login;
</select>
</mapper>
Mapper代理开发
- 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
- 设置SQL映射文件的namespace属性为Mapper接口全限定名
- 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id并保持参数类型和返回值类型一致
- 编码:
- 通过SqlSession的getMapper方法获取Mapper接口的代理对象
- 调用对应方法完成sql的执行
细节:如果Mapper接口名称和SQL映射文件名称相同,并且在同一目录下,则可使用包扫描的方式简化sql映射文件的加载
//1. 加载mysql的核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取sqlSession对象,用它库执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 执行sql
//List<USer> users = sqlSession.selectList("test.selectAll");
//获取BrandMapper代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
List<Brand> brands = brandmapper.selectAll();
System.out.println(brands);
sqlSession.close();
MyBatis核心配置文件
顶层结构
configuration(配置)
-
Properties(属性)
-
settings(设置)
-
typeAliases(类型别名)
-
typeHandlers(类型处理器)
-
objectFactory(对象工厂)
-
plugins(插件)
-
environments(环境配置)
environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
-
darabaseldProvider(数据库厂商标识)
-
mapper(映射器)
配置便签时,要注意遵守前后顺序
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>
<typeAliases>
<package name="com.pugo"/>
</typeAliases>
//起别名之后涉及到USer的实体类是可以直接写user并且不用区分大小写
<!--
environments:配置数据库连接环境信息的,可以配置多个environment,通过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://127.0.0.1:3306/mybatis_demo"/>
//数据库,端口,
<property name="username" value="root"/>
//账户名
<property name="password" value="ROOT"/>
//密码
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/blog"/>
<property name="username" value="root"/>
<property name="password" value="ROOT"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--包扫描的方式加载映射文件 -->
<package name="com.mapper"/>
</mappers>
</configuration>
配置文件完成增删改查
用一个案例来演示
要完成的功能列表清单
-
查询
查询所有数据
查看情况
条件查询
-
添加
-
修改
修改全部字段
修改动态字段
-
删除
删除一个
批量删除
查看所有数据
数据库名和实体类名不一样
数据库表的字段名称 和 实体类的属性名称不一样,则不能自动封装数据
-
起别名:对不一样的列名起别名和实体类的属性名一样
select id,brand_name as brandName,company_name as companyName,order from tb_brand;
缺点:每次查询都要定义一次别名
可以使用sql片段
<sql id="sqlbrand"> -
resultMap:定义
<resultMap>标签,在<select>标签中,使用resultMap属性替换resultType属性id:唯一标识
type:映射的类型,支持别名
<resultMap id="brandResultMap" type="brand"> <result column="brand_name" property="brandName"/> <result column="company_name" property="companyName"/> <resultMap> <select id="selectAll" rseultMap="brandResultMap">resultMap的标签内部:
id:完成主键字段的映射
- column:表的列名
- property:实体类的属性名
result:完成一般字段的映射
- column:表的列名
- property:实体类的属性名
编写接口方法:Mapper接口
- 参数:无
- 结果:List
<Brand>
编写SQL语句:SQL映射文件
执行方法,测试
BrandMapper.java,BrandMapper接口
package com.mapper;
import com.pugo.Brand;
import java.util.List;
public interface BrandMapper {
List<Brand> selectAll();
}
BrandMapper.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">
<!--
namepace:名称空间
-->
<mapper namespace="com.mapper.BrandMapper">
<select id="selectAll" resultType="Brand">
select *
from tb_brand;
</select>
</mapper>
MybatisTest.java,测试代码
public class MybatisTest {
@Test
public void test() throws IOException {
//1. 加载mysql的核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取sqlSession对象,用它库执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 执行sql
//List<USer> users = sqlSession.selectList("test.selectAll");
//获取BrandMapper代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
List<Brand> brands = brandmapper.selectAll();
System.out.println(brands);
sqlSession.close();
}
}
查看详情
-
编写接口方法:Mapper接口
参数:id
结果:Brand
-
编写SQL语句:SQl映射文件
<select id="selectByld" parameterType="int" resultType="brand"> select * from tb_brand where id=#{id};</select> -
执行方法,测试
参数占位符:
-
{}:会将其替换为?,为了防止SQL注入
- ${}:拼sql。会有SQL注入问题
- 使用时机:
- 参数传递的时候:#{}
- 表名或者列名不固定的情况下:${}会存在SQL注入问题
参数类型:parameterType:可以省略
特殊字符处理:
- 转义字符:<(小于号)的转义字符 &it
- CDATA区:
<![CDATA[ < ]]>
List<Brand> selectByid(int id);
<-- -->
<select id="selectByid" resultType="com.pugo.Brand">
select *
from tb_brand where id=#{id};
</select>
List<Brand> brands = brandmapper.selectByid(id);
查询-多条件查询
-
编写接口方法:Mapper接口
参数:所有查询条件
结果:List
<Brand> -
编写SQL语句:SQL映射文件
-
执行方法,测试
参数接收:
-
散装参数:如果方法中有多个参数,需要使用@Param("SQL参数占位符名称")
List<Brand> selectByCondition(@Param("status") int status,@Param("companyName") String companyName) -
对象参数:对象的属性名要和参数的名称对应
List<Brand> selectByCondition(Brand brand); //Brand类的属性名要和需要的参数名对应,属性的值就是参数的值<select id="selectByCondition" resultType="com.pugo.Brand"> select * from tb_brand where id=#{id} and company_name like #{company_name} and brand_name like #{brand_name}; </select>int start = 1; String companyName="三只松鼠"; String brandName=""; companyName = "%"+companyName+"%"; brandName = "%"+brandName+"%"; Brand brand = new Brand(); brand.setId(start); brand.setBrand_name(brandName); brand.setCompany_name(companyName); List<Brand> brands = brandmapper.selectByCondition(brand); -
map集合参数:其中的键要和参数名对应
List<Brand> selectByCondition(Map map); //Map中的键名要和参数名称对应,键值就是参数值Map map= new HashMap(); map.put("id",id); map.put("companyName",compantName); map.put("brandName",brandName);
查询-多条件-动态条件查询动态SQL
动态SQL
if:用于判断参数是否有值,使用test属性进行条件判断
存在的问题:第一个条件不需要逻辑运算符
解决方法:
-
使用恒等式让所有条件的格式都一样
在where后面加上1=1,所有的都加上and
-
<where>标签替换where关键字<where> <if test="compantName !=null and companyName !=''"> and company_name like #{companyName}</if> <if test="brandName!=null"> and brandName like #{brandName}</if> </where>
从多个条件中选一个
choose(when,otherwise):选择,类似java中的switch语句
select * from tb_brand
<where>
<choose><!-- 类似与switch-->
<when test="status!=null"><!-- 类似于case-->
status=#{status}
</when>
<otherwise><!--类似于default-->
1=1
</otherwise>
</choose>
</where>
添加
编写接口方法:Mapper接口 void add(Brand brand);
- 参数:除了id之外的所有数据
- 结果:void
编写SQL语句:SQL映射文件
<insert id="add">
insert into tb_brand(brand_name,company_name,ordered,description,status) values(#{brandName},#{companyName},#{ordered},#{description},#{status});
</insert>
执行方法,测试
-
MyBatis事务
openSession():默认开启事务,进行增删改操作后需要使用sqlSession.commit()去手动提交事务
String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2. 获取sqlSession对象,用它库执行sql SqlSession sqlSession = sqlSessionFactory.openSession(); //执行sql //获取BrandMapper代理对象 BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class); //执行方法 brandmapper.add(brand); //提交事务 sqlSession.commit(); //释放资源 sqlSession.close();openSession(true):可以设置为自动提交事务(关闭事务)
//2. 获取sqlSession对象,用它库执行sql SqlSession sqlSession = sqlSessionFactory.openSession(true);
添加的主键返回,让主键能在添加的类的没有设但主键自增的值能实时返回,在添加后就能通过实体类使用。<insert useGeneratedKeys="true" keyProperty="id">
<insert useGeneratedKeys="true" keyProperty="id">
//执行方法
brandmapper.add(brand);
//提交事务
sqlSession.commit();
Integer id=brand.getid();
System.out.println(id);
//id能打印出来就是主键自增的那个值
//释放资源
sqlSession.close();
修改
编写接口方法:Mapper接口 void update(Brand brand)
- 参数:所有数据
- 结果:void
编写SQL语句:SQL映射文件
<update id="update">
update tb_brand set brand_name=#{brandName},company_name=#{companyName},orderd=#{orderd},description=#{description},status=#{status}
where id = #{id}
</update>
执行方法。测试
动态修改
<set>,<if>标签
<update id="updateBrand">
update tb_brand
<set>
<if test="brand_name!=null and brand_name!=''">
brand_name=#{brand_name},
</if>
<if test="company_name!=null and company_name!=''">
company_name=#{company_name},
</if>
<if test="orderd!=null">
orderd=#{orderd},
</if>
<if test="description!=null and description!=''">
description=#{description},
</if>
<if test="status!=null and status!=''">
status=#{status}
</if>
</set>
where id = #{id};
删除
sqlw文件:
<delete id="deleteByid">
delete from tb_brand where id=#{id};
</delete>
批量删除
接收一个id数组,循环遍历删除
mybatis会将数组参数,封装为一个map集合
- 默认:array=数组
- 使用@Param注解改变map集合的默认名称(@Param(ids))在BrandMApper方法中的参数ids前放上注解
<foreach>:循环遍历便签
collection:循环的对象,item:循环时的名称
separator:用什么分隔符,比如 ,,open:开始添加什么,close:结束时添加什么
<delete id="deleteByid">
delete from tb_brand where id
in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
参数传递
MyBatis参数封装:
-
POJO类型(实体类):直接使用,属性名和参数占位符名称一致
-
Map集合:直接使用,键名和参数占位符名称一致
-
Collection:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map.put("arg0",collection集合);
map.put("collection",collection集合)
-
List:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map.put("arg0",List集合);
map.put("collection",List集合)
map.put("List",List集合)
-
Array:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map.put("arg0",Array集合);
map.put("array",Array集合)
-
其他类型:直接使用
多个参数:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map.put("arg0",参数1);
map.put("param1",参数2);
map.put("param2",参数3);
map.put("arg1",参数4);
----------------@Param("username")
map.put("username",参数1);
map.put("param1",参数2);
map.put("param2",参数3);
map.put("arg1",参数4);
使用@Param注解
注解完成增删改查
注解完成简单功能
配置文件完成复杂功能
@Select("select * from tb_brand where id=#{id}")
public Brand selectByid(int id);
在mapper上的方法上面写这个注解
- 查询:@Select
- 添加:@Insert
- 修改:@Update
- 删除:@Delete

浙公网安备 33010602011771号