ORM
ORM(Object Relational Mapping)是一种将对象模型与关系数据库之间进行映射的技术,它可以让开发者使用面向对象的方式来操作数据库,而无需编写SQL语句。
常见的ORM框架有
- MyBatis
- Spring Data JPA
简介
什么是MyBatis?
-
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
-
MyBatis原本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
-
官网:https://mybatis.org/mybatis-3/zh/index.html
什么是持久层?
- 指的是就是数据访问层(dao),是用来操作数据库的。
什么是框架?
- 是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。
- 在框架的基础上进行软件开发更加高效、规范、通用、可拓展。
JDBC和MyBatis对比
原始的JDBC程序操作数据库操作步骤:
- 注册驱动
- 获取连接对象
- 执行SQL语句,返回执行结果
- 处理执行结果
- 释放资源
直接基于JDBC程序来操作数据库,代码实现非常繁琐,所以在项目开发中,我们很少使用。 在项目开发中,通常会使用Mybatis这类的高级技术来操作数据库,从而简化数据库操作、提高开发效率。
Mybatis框架,就是对原始的JDBC程序的封装。
问题分析
原始的JDBC程序,存在以下几点问题:
- 数据库链接的四要素(驱动、链接、用户名、密码)全部硬编码在java代码中
- 查询结果的解析及封装操作繁琐
- 每一次查询数据库都需要获取连接,操作完毕后释放连接, 资源浪费, 性能降低
技术对比
分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的:
- 数据库连接四要素(驱动、链接、用户名、密码),都配置在配置文件中
- 查询结果的解析及封装,由mybatis自动完成映射封装
- 在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。
入门案例
以前我们是在图形化客户端工具中编写SQL查询代码,发送给数据库执行,数据库执行后返回操作结果。
图形化工具会把数据库执行的查询结果,使用表格的形式展现出来
现在使用Mybatis操作数据库,就是在Mybatis中编写SQL查询代码,发送给数据库执行,数据库执行后返回结果。
Mybatis会把数据库执行的查询结果,使用实体类封装起来(一行记录对应一个实体类对象)
代码实现
-
创建mybatis模块,并添加依赖
<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> </dependencies>
-
在resources 目录下创建mybatis的配置文件
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> <!-- environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment --> <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:///mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </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:///mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!--加载sql映射文件--> <mapper resource="UserMapper.xml"/> </mappers> </configuration>
-
创建mybatis数据库,执行下面的代码创建用户表user,并创建对应的实体类User。
- 用户表:
-- 用户表 create table user( id int unsigned primary key auto_increment comment 'ID', name varchar(100) comment '姓名', age tinyint unsigned comment '年龄', gender tinyint unsigned comment '性别, 1:男, 2:女', phone varchar(11) comment '手机号', update_time datetime comment '修改时间' ) comment '用户表'; -- 测试数据 insert into user(id, name, age, gender, phone,update_time) VALUES (null,'白眉鹰王',55,'1','18800000000',now()); insert into user(id, name, age, gender, phone,update_time) VALUES (null,'金毛狮王',45,'1','18800000001',now()); insert into user(id, name, age, gender, phone,update_time) VALUES (null,'青翼蝠王',38,'1','18800000002',now()); insert into user(id, name, age, gender, phone,update_time) VALUES (null,'紫衫龙王',42,'2','18800000003',now()); insert into user(id, name, age, gender, phone,update_time) VALUES (null,'光明左使',37,'1','18800000004',now()); insert into user(id, name, age, gender, phone,update_time) VALUES (null,'光明右使',48,'1','18800000005',now());
-
实体类
- 实体类的属性名与表中的字段名一一对应。
public class User { private Integer id; //id(主键) private String name; //姓名 private Short age; //年龄 private Short gender; //性别 private String phone; //手机号 private LocalDateTime updateTime; //修改时间 //省略get、set、toString方法 }
LocalDateTime类型对应数据表中的datetime类型
LocalDate类型对应数据表中的date类型
-
在模块的
resources
目录下创建映射配置文件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="UserMapper"> <select id="listUser" resultType="com.fs.pojo.User"> select * from user; </select> </mapper>
resultType
属性用于配置数据封装的类型(类的全限定名)
功能测试
创建MyBatisTest
public class MyBatisTest {
@Test
public void test() throws IOException {
//加载mybatis核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取SqlSession对象,用来执行sql
SqlSession session = sqlSessionFactory.openSession();
//执行sql
//使用映射配置文件中的namespace.id来定位sql语句
List<User> users = session.selectList("UserMapper.listUser");
for (User user : users) {
System.out.println(user);
}
//释放资源
session.close();
}
}
代理开发
作用:
- 解决mybatis原生方式中执行sql语句时的硬编码
- 简化后期执行SQL
代码实现
-
创建UserMapper接口
public interface UserMapper { List<User> listUser(@Param("id") Integer id, @Param("age") Integer age, @Param("gender") Integer gender); }
-
修改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> <!--name属性的值是实体类所在包--> <package name="com.fs.pojo"/> </typeAliases> <!-- environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment --> <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:///mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </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:///mybatis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!--加载sql映射文件--> <mapper resource="UserMapper.xml"/> </mappers> </configuration>
如果Mapper接口名称和SQL映射文件名称相同,并且Mapper接口和SQL映射文件在相同的目录层级结构下,则可以使用包扫描的方式简化SQL映射文件的加载。
<mappers> <!--配置Mapper代理接口包扫描--> <package name="com.fs.mapper"/> </mappers>
-
修改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"> <!-- namespace:名称空间。必须是对应接口的全限定名 --> <mapper namespace="com.fs.mapper.UserMapper"> <select id="listUser" resultType="User"> select * from user where id < #{id} and age > #{age} and gender != #{gender}; </select> </mapper>
可以使用
类型别名
(typeAliases)简化resultType
属性。sql语句中特殊字符的处理:
-
使用字符实体
小于号:<
-
<![CDATA[需要转义的字符]]>
<![CDATA[<]]>
-
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(); //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<User> users = userMapper.listUser(6,37,2); for (User user : users) { System.out.println(user); } //释放资源 session.close(); } }
参数占位符
在Mybatis中提供的参数占位符有两种:${…} 、#{…}
-
#{…}
- 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值,底层使用的是
PreparedStatement
- 一般在参数传递时使用
- 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值,底层使用的是
-
${…}
- 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题,底层使用的是
Statement
- 一般在对表名、列表进行动态设置时使用
- 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题,底层使用的是
项目开发中,建议使用#{…},生成预编译SQL,防止SQL注入安全。
参数传递
多个参数
在接口方法中定义多个参数时,Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,而键在没有使用 @Param
注解时有以下命名规则:
-
以 arg 开头 :第一个参数就叫 arg0,第二个参数就叫 arg1,以此类推。如:
map.put(“arg0”,参数值1);
map.put(“arg1”,参数值2);
-
以 param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推。如:
map.put(“param1”,参数值1);
map.put(“param2”,参数值2);
接收多个参数使用 @Param
注解后Mybatis 会将默认的键名替换为对应注解的属性值。
代码实现
-
修改UserMapper
public interface UserMapper { List<User> listUser(Integer id, Integer age, Integer gender); }
-
修改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"> <!-- namespace:名称空间。必须是对应接口的全限定名 --> <mapper namespace="com.fs.mapper.UserMapper"> <select id="listUser" resultType="User"> select * from user where id < #{param1} and age > #{param2} and gender != #{param3}; </select> </mapper>
或
<?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.fs.mapper.UserMapper"> <select id="listUser" resultType="User"> select * from user where id < #{arg0} and age > #{arg1} and gender != #{arg2}; </select> </mapper>
单个参数
POJO 类型参数
直接使用。
要求 属性名
和 参数占位符名称
一致
Map 集合类型
直接使用。
要求 map集合的键名
和 参数占位符名称
一致
Collection 集合类型
Mybatis 会将集合封装到 map 集合中:
- map.put(“arg0”,collection集合);
- map.put(“collection”,collection集合;
可以使用
@Param
注解替换map集合中默认的键名。
List 集合类型
Mybatis 会将集合封装到 map 集合中:
- map.put(“arg0”,list集合);
- map.put(“collection”,list集合);
- map.put(“list”,list集合);
可以使用
@Param
注解替换map集合中默认的键名。
Array 类型
Mybatis 会将数组封装到 map 集合中,如下:
- map.put(“arg0”,数组);
- map.put(“array”,数组);
可以使用
@Param
注解替换map集合中默认的键名。
基本类型
直接使用。
参数占位符名称
叫什么都可以。尽量做到见名知意
数据封装
如果实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装,如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。
起别名
代码实现
-
修改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="com.fs.mapper.UserMapper"> <select id="listUser" resultType="User"> select id, name, age, gender, phone, update_time as updateTime from user; </select> </mapper>
配置resultMap映射
代码实现
-
修改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="com.fs.mapper.UserMapper"> <resultMap id="UserResultMap" type="User"> <result column="update_time" property="updateTime"/> </resultMap> <select id="listUser" resultMap="UserResultMap"> select * from user; </select> </mapper>
完成主键字段的映射:
- column:表的列名
- property:实体类的属性名
完成一般字段的映射:
- column:表的列名
- property:实体类的属性名
基本使用
删除
代码实现
-
修改UserMapper
public interface UserMapper { int deleteById(Integer id); }
-
修改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="com.fs.mapper.UserMapper"> <delete id="deleteById"> delete from user where id = #{id} </delete> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(); //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); System.out.println(userMapper.deleteById(6)); //提交事务 session.commit(); //释放资源 session.close(); } }
MyBatis的事务默认为手动提交
SqlSession sqlSession = sqlSessionFactory.openSession(true); //设置自动提交事务
添加
代码实现
-
修改UserMapper
public interface UserMapper { int insertUser(User user); }
-
修改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="com.fs.mapper.UserMapper"> <insert id="insertUser"> insert into user (name, age, gender, phone, update_time) value (#{name}, #{age}, #{gender}, #{phone}, #{updateTime}) </insert> </mapper>
-
创建MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务 //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setName("光明右使"); user.setAge((short) 48); user.setGender((short) 1); user.setPhone("18800000005"); user.setUpdateTime(LocalDateTime.now()); System.out.println(userMapper.insertUser(user)); //释放资源 session.close(); } }
主键返回
在数据添加成功后,返回插入数据库数据的主键。
代码实现
-
修改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="com.fs.mapper.UserMapper"> <insert id="insertUser" useGeneratedKeys="true" keyProperty="id"> insert into user (name, age, gender, phone, update_time) value (#{name}, #{age}, #{gender}, #{phone}, #{updateTime}) </insert> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务 //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setName("光明右使"); user.setAge((short) 48); user.setGender((short) 1); user.setPhone("18800000005"); user.setUpdateTime(LocalDateTime.now()); System.out.println(userMapper.insertUser(user)); System.out.println(user); //释放资源 session.close(); } }
修改
代码实现
-
修改UserMapper
public interface UserMapper { int updateUser(User user); }
-
修改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="com.fs.mapper.UserMapper"> <update id="updateUser"> update user set name = #{name}, age = #{age}, gender = #{gender}, phone = #{phone}, update_time = #{updateTime} where id = #{id} </update> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务 //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setId(6); user.setName("光明大使"); user.setAge((short) 58); user.setGender((short) 2); user.setUpdateTime(LocalDateTime.now()); System.out.println(userMapper.updateUser(user)); System.out.println(user); //释放资源 session.close(); } }
动态SQL
SQL语句会随着用户的输入或外部条件的变化而变化
动态查询
<if>
-
用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。
<if test="条件表达式"> </if>
<where>
-
只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR
<where> </where>
代码实现
-
修改UserMapper
public interface UserMapper { List<User> listUser(@Param("id") Integer id, @Param("age") Integer age, @Param("gender") Integer gender); }
-
修改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="com.fs.mapper.UserMapper"> <select id="listUser" resultType="User"> select * from user <where> <if test="id != null"> id < #{id} </if> <if test="age != null"> and age > #{age} </if> <if test="gender != null"> and gender != #{gender} </if> </where> </select> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(); //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<User> users = userMapper.listUser(null,37,2); for (User user : users) { System.out.println(user); } //释放资源 session.close(); } }
动态修改
<set>
-
动态的在SQL语句中插入set关键字,并会删掉额外的逗号。
<set> </set>
代码实现
-
修改UserMapper
public interface UserMapper { int updateUser(User user); }
-
修改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="com.fs.mapper.UserMapper"> <update id="updateUser"> update user <set> <if test="name != null"> name = #{name}, </if> <if test="age != null"> age = #{age}, </if> <if test="gender != null"> gender = #{gender}, </if> <if test="phone != null"> phone = #{phone}, </if> <if test="updateTime != null"> update_time = #{updateTime} </if> </set> where id = #{id} </update> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务 //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setId(6); user.setName("光明大使"); user.setAge((short) 58); user.setGender((short) 2); user.setUpdateTime(LocalDateTime.now()); System.out.println(userMapper.updateUser(user)); System.out.println(user); //释放资源 session.close(); } }
批量删除
foreach
-
用来迭代任何可迭代的对象(如数组,集合)
<foreach collection="集合名称" item="集合遍历出来的元素/项" separator="集合项迭代之间的分隔符" open="遍历开始前拼接的片段" close="遍历结束后拼接的片段"> </foreach>
代码实现
-
修改UserMapper
public interface UserMapper { int deleteById(@Param("ids") int[] ids); }
-
修改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="com.fs.mapper.UserMapper"> <delete id="deleteById"> delete from user where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(); //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); System.out.println(userMapper.deleteById(new int[]{1,2,3})); //提交事务 session.commit(); //释放资源 session.close(); } }
sql、include
<sql>
-
定义可重用的SQL片段
<sql id="SQL片段id"> </sql>
<include>
-
通过属性refid,指定包含的SQL片段
<include refid="SQL片段id"></include>
代码实现
-
修改UserMapper
public interface UserMapper { List<User> listUser(@Param("id") Integer id, @Param("age") Integer age, @Param("gender") Integer gender); }
-
修改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="com.fs.mapper.UserMapper"> <sql id="list"> select * from user </sql> <select id="listUser" resultType="User"> <include refid="list"></include> <where> <if test="id != null"> id < #{id} </if> <if test="age != null"> and age > #{age} </if> <if test="gender != null"> and gender != #{gender} </if> </where> </select> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(); //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<User> users = userMapper.listUser(null,37,2); for (User user : users) { System.out.println(user); } //释放资源 session.close(); } }
注解开发
Mybatis的开发有两种方式:
- 注解
- XML
注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement
使用Mybatis的注解,主要是来完成一些简单的增删改查功能。
代码实现
-
修改UserMapper
public interface UserMapper { @Select("select * from user;") List<User> listUser(); }
@Select注解:用于编写select查询操作的SQL语句
@Delete注解:用于编写delete操作的SQL语句
@Update注解:用于编写update操作的SQL语句
@Insert注解:用于编写insert操作的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="com.fs.mapper.UserMapper"> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(); //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<User> users = userMapper.listUser(); for (User user : users) { System.out.println(user); } //释放资源 session.close(); } }
主键返回
在Mapper接口中的方法上添加一个@Options
注解,并在注解中指定属性useGeneratedKeys=true和keyProperty=“实体类属性名”
代码实现
-
修改UserMapper
public interface UserMapper { @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into user (name, age, gender, phone, update_time)\n" + " value (#{name}, #{age}, #{gender}, #{phone}, #{updateTime})") int insertUser(User user); }
-
修改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="com.fs.mapper.UserMapper"> </mapper>
-
创建MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务 //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setName("光明右使"); user.setAge((short) 48); user.setGender((short) 1); user.setPhone("18800000005"); user.setUpdateTime(LocalDateTime.now()); System.out.println(userMapper.insertUser(user)); System.out.println(user); //释放资源 session.close(); } }
配置result映射
通过 @Results及@Result进行结果映射
代码实现
-
修改UserMapper
public interface UserMapper { @Results({ @Result(column = "update_time", property = "updateTime") }) @Select("select * from user;") List<User> listUser(); }
-
修改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="com.fs.mapper.UserMapper"> </mapper>
-
修改MyBatisTest
public class MyBatisTest { @Test public void test() throws IOException { //加载mybatis核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象,用来执行sql SqlSession session = sqlSessionFactory.openSession(); //执行sql //获取UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<User> users = userMapper.listUser(); for (User user : users) { System.out.println(user); } //释放资源 session.close(); } }
@Results源代码:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Results { String id() default ""; Result[] value() default {}; //Result类型的数组 }
@Result源代码:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Repeatable(Results.class) public @interface Result { boolean id() default false;//表示当前列是否为主键(true:是主键) String column() default "";//指定表中字段名 String property() default "";//指定类中属性名 Class<?> javaType() default void.class; JdbcType jdbcType() default JdbcType.UNDEFINED; Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class; One one() default @One; Many many() default @Many; }
SqlSessionFactory工具类抽取
重复代码:
//加载mybatis核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- 重复代码不利于后期的维护
- SqlSessionFactory工厂类进行重复创建,资源消耗非常大但性能却非常低。
代码实现
public class SqlSessionFactoryUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
//静态代码块会随着类的加载而自动执行,且只执行一次
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
工具类抽取以后,以后在对Mybatis的SqlSession进行操作的时候,就可以直接使用
SqlSessionFactory sqlSessionFactory =SqlSessionFactoryUtils.getSqlSessionFactory();