前言
MyBatis是一个Java持久化框架,它通过XML描述符或注解把对象与存储过程或SQL语句关联起来。
MyBatis是在Apache许可证 2.0下分发的自由软件,是iBATIS 3.0的分支版本。其维护团队也包含iBATIS的初创成员。(维基百科)
引入依赖
在Maven项目中引入MyBatis的jar包
编辑pom.xml文件
1 2 3 4 5
| <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.1</version> </dependency>
|
创建配置文件
- 在
src/main/resources目录下新建mybatis-config.xml全局配置文件
1 2 3 4 5 6 7 8 9
| <?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>
</configuration>
|
- 在
src/main/resources目录下新建XxxMapper.xmlMapper配置文件
1 2 3 4 5 6 7 8 9 10 11 12
| <?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>
|
向全局配置文件引入Mapper配置文件
详细步骤传送门
MyBatis实现增删改查
- 读取mybatis的核心配置文件(mybatis-config.xml)
- 通过配置信息获取一个SqlSessionFactory工厂对象
- 通过工厂获取一个SqlSession对象
1 2 3 4 5 6 7 8 9 10 11 12
| SqlSession session;
@Before public void testBefore() throws IOException { InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory fac = sqlSessionFactoryBuilder.build( in ); session = fac.openSession(true); }
|
增
1 2 3
| <insert id="ins"> INSERT INTO emp VALUES(null, "赵云", "保安", 6000.0) </insert>
|
1 2 3 4 5
| @Test public void testIns() { int rol = session.insert("EmpMapper.ins"); System.out.println("影响的行数:"+rol); }
|
占位符(多个)
1 2 3
| <insert id="ins"> INSERT INTO emp VALUES(null, #{name}, #{job}, #{salary}) </insert>
|
通过POJO对象传参
1 2 3 4 5 6 7 8 9
| @Test public void testIns() { Emp emp = new Emp(); emp.setName("赵云"); emp.setJob("保安"); emp.setSalary(6000.0); int rol = session.insert("EmpMapper.ins", emp); System.out.println("影响的行数:"+rol); }
|
通过map对象传参
1 2 3 4 5 6 7 8 9
| @Test public void testIns() { Map map = new HashMap(); map.put("name", "赵云"); map.put("job", "保安"); map.put("salary", 6000.0); int rol = session.insert("EmpMapper.ins", map); System.out.println("影响的行数:"+rol); }
|
删
1 2 3
| <delete id="del"> DELETE FROM emp </delete>
|
1 2 3 4 5
| @Test public void testDel() { int rol = session.insert("EmpMapper.del"); System.out.println("影响的行数:"+rol); }
|
占位符
改
1 2 3
| <update id="upd"> UPDATE emp SET job='保镖', salary=20000.0 WHERE name='赵云' </update>
|
1 2 3 4 5
| @Test public void testUpd() { int rol = session.insert("EmpMapper.upd"); System.out.println("影响的行数:"+rol); }
|
占位符
查
查全部
1 2 3
| <select id="findAll" resultType="com.pojo.Emp"> SELECT * FROM emp </select>
|
1 2 3 4
| List<Emp> list = session.selectList("EmpMapper.findAll"); for(Emp e : list) { System.out.println(e); }
|
查指定行(占位符)
1 2 3
| <select id="fin2" resultType="com.pojo.Emp"> SELECT * FROM emp WHERE name=#{name} </select>
|
- 如果只有一个参数,可以直接使用重载方法
- 如果返回结果只有一条,可以直接使用selectOne只接收一条
1 2 3 4 5
| @Test public void testFin2() { Emp emp = session.selectOne("EmpMapper.fin2", "赵云"); System.out.println(emp); }
|
查指定列(占位符)
1 2 3
| <select id="fin3" resultType="com.pojo.Emp"> SELECT ${cols} FROM emp </select>
|
1 2 3 4 5 6 7 8 9
| @Test public void testFin3() { Map map = new HashMap(); map.put("cols", "name,job"); List<Emp> selectList = session.selectList("EmpMapper.fin3", map); for (Emp emp:selectList) { System.out.println(emp.getName()+"\t"+emp.getJob()); } }
|
占位符
两种占位符示例(索引)
传送门
传送门
三种传参方式示例(索引)
传送门
传送门
传送门
两种占位符的区别
#{}在接收到数据后,如果是日期类型或字符串类型,会在前后添加引号,适用于指定值
${}在接收到数据后,会直接将数据拼接到SQL语句中,适用于指定SQL子句
${}如果指定了POJO对象不存在的成员变量,只能用map方式传参
标签和参数
<select></select>:查询语句
id:与@Mapper所标注的类中方法名相对应
resultType:与@Mapper所标注的类中方法返回值类型(的别名)相对应
resultMap:传送门
<insert></insert>:插入语句
parameterType:用于设置参数的类型,可以省略
useGeneratedKeys:值为true时表示使用主键
useGeneratedKeys:值为true时表示使用主键
keyProperty:指定主键名
<update></update>:修改语句
<delete></delete>:删除语句
<sql></sql>:传送门
MyBatis动态SQL标签
choose…when
1 2 3 4 5 6 7 8 9 10 11
| <choose> <when test="username == 1"> ... </when> <when test="username == 2"> ... </when> <otherwise> ... </otherwise> </choose>
|
where
if
1 2 3
| <if test="username != null"> ... </if>
|
foreach
ids:从外面传递的集合
1 2 3
| <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach>
|
面向接口开发
条件
- 写一个接口,接口的全类名等于对应Mapper文件的namespace值
- 接口中的方法名要对应Mapper文件中SQL标签的id值
- 如果是查询,select标签上的resultType类型和接口中的方法的返回值类型保持一致(如果接口返回List<泛型>,resultType只需要指定集合中泛型即可)
- 接口中的方法的参数类型和SQL标签上的参数类型(可以不指定)保持一致
示例
- 修改
EmpMapper.xml中<mapper></mapper>标签内namespace的值为对应接口的全局限定名
1 2 3
| <mapper namespace="com.dao.EmpMapper"> ... </mapper>
|
- 在dao包下创建
EmpMapper接口
- 接口内提供各种功能的抽象方法,根据SQL语句修改返回值类型
@Param(""):定义映射到数据表的字段名
1 2 3
| public interface EmpMapper { public List<Emp> findAll(@Param("name") String name); }
|
- 方法名需要和
EmpMapper.xml内的对应标签的id值相同
1 2 3
| <select id="findAll" resultType="com.pojo.Emp"> select * from emp </select>
|
- 在测试类中,使用session对象,通过反射,获取
EmpMapper实现类(我们只需要定义接口,实现类由框架为我们提供)
- 通过mapper对象调用对应方法实现增删改查
1 2 3 4 5 6 7 8
| @Test public void testFindAll() { EmpMapper mapper = session.getMapper(EmpMapper.class); List<Emp> findAll = mapper.findAll(); for (Emp emp : findAll) { System.out.println(emp); } }
|
面向注解开发
示例
- 在面向接口开发的基础上,可以删除
EmpMapper.xml文件
- 在接口定义的抽象方法上使用注解
@Insert、@Delete、@Update、@Select作增删改查操作
1 2 3 4
| public interface EmpMapper { @Select("select * from emp") public List<Emp> findAll(); }
|
- 注意:不允许重载方法,原因是面向注解开发不允许出现同名方法
在注解中使用标签
- 在注解中定义的SQL,如果使用
<script></script>包裹,那么可以在内部使用其他Mybatis动态SQL标签
1 2 3 4
| public interface EmpMapper { @Select("<script>select * from emp</script>") public List<Emp> findAll(); }
|
Mapper.xml特殊符号处理方式
使用html转义字符
使用CDATA区存放特殊符号
MyBatis的xml实现sql代码的复用
- 将重复语句写在
<sql></sql>标签内,在其他语句通过id属性引用
1 2 3 4 5 6 7
| <sql id="id1"> ... </sql>
<select id="id2"> <include refid="id1" /> </select>
|
jdbc注册信息写入properties文件
- 在
src/main/resources目录下新建jdbc.properties配置文件
1 2 3 4
| jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8&serverTimezone=UTC jdbc.username=root jdbc.password=123456
|
- 在
mybatis-config.xml的<configuration></configuration>标签哪引入
1 2 3
| <configuration> <properties resource="jdbc.properties"/> </configuration>
|
- 将
mybatis-config.xml内的jdbc注册信息由常量改成变量
1 2 3 4 5 6
| <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>
|
自定义映射
- resultMap为框架中实现高级映射时采用的一种映射策略
- 主要用于表中字段与类中属性不匹配、用于多表嵌套查询、用于多表关联查询
定义一个查询
1 2 3
| <select id="" resultMap=""> ... </select>
|
一对一
resultMap->id:与查询语句的resultMap值相对应
resultMap->type:返回值实体类的全局限定名
<id></id>:主键字段映射
<result></result>:自定义映射
column:对应的查询到结果的数据表字段
property:对应的类的属性名
1 2 3 4
| <resultMap id="" type=""> <id property="id" column="id"></id> <result property="name" column="name"></result> </resultMap>
|
一对多
ofType:结果集中每个结果的类型
collection->select:嵌套查询。@Mapper所标注的类中方法的全局限定名
collection->column与result->column:均为对应的查询到结果的数据表字段,如果相同可以省略<result></result>
1 2 3 4 5
| <resultMap id="" type=""> <collection id="" column="" property="" ofType="" select=""> <result column=""></result> </collection> </resultMap>
|
多对一
1 2 3 4
| <resultMap id="" type=""> <association id="" column="" property="" select=""> </association> </resultMap>
|
List结果转换为Map结果
@MapKey("id"):指定每个值转换Map后的键
1 2 3 4 5
| public interface UserMapper { @MapKey("id") @Select("SELECT * FROM user") Map<Integer, User> method(); }
|
完成