什么是Mybatis?
Mybatis是一个持久层框架(ORM),简单理解就是对JDBC的封装。
ORM:Object Relationship Mapping
对象关系映射。
- 对象:面向对象
- 关系:关系型数据库
- 映射:Java到Mysql的映射,开发者可以用面向对象的思想来管理数据库。
使用步骤
- 引入依赖
- Mybatis的配置文件
- 编写配置文件
- 注册
- 关闭
为什么用Mybatis?
优点
- 与JDBC相比,减少了50%以上的代码量
- 简单易学
- 灵活;SQL是写在XML中的,降低耦合度,便于统一管理和优化
- 提供XML标签,支持编写动态SQL语句
- 提供映射标签,支持对象与数据库的ORM字段关系映射。
缺点
- SQL语句需要亲自编写,工作量大。(
hibernate能够自动生成SQL语句
) - SQL语句依赖于数据库,可移植性差,不能随意更换数据库。
怎么用Mybatis?
-
新建Maven工程,在
pom.xml
中引入相关依赖。<!--mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!--mysql数据库驱动jar--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency>
-
配置
mybatis-config.xml
(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"> <configuration> <!--配置Mybatis的运行环境--> <environments default="development"> <environment id="development"> <!--配置JDBC事物--> <transactionManager type="JDBC"/> <!--POOLED配置JDBC数据源链接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> </configuration>
-
新建
数据库表
CREATE TABLE `user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `age` int DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-
新建数据库表对应的
实体类
@Data @AllArgsConstructor @NoArgsConstructor public class User { private Integer id; private String username; private String password; private Integer age; }
-
开发
DAO接口
– mybatis中,接口中不能定义方法的重载。
public interface UserDao { //保存用户 int save(User user); }
-
开发
Mapper配置文件
– 在mybatis中,一个DAO接口对应一个Mapper配置文件
– Resources下创建文件夹要用
/
分隔。(com/ibear/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文件是对哪个DAO接口的实现 全限定名:包.类 --> <mapper namespace="com.ibear.dao.UserDao"> <!--保存 insert:插入操作 id:接口中对应的方法名 parameterType:和接口中对应方法的参数类型一致 -> 全限定名:包.类 (#{id},#{username},#{password},#{age}): 需要与数据库列名一致,顺序也要一致 useGeneratedKeys="true":使用数据库的id自动生成策略(加不加都行,此策略只支持mysql) keyProperty="id":主键属性:当使用数据库主键自动生成策略时,将自动返回生成的id --> <insert id="save" parameterType="com.ibear.entity.User" keyProperty="id" useGeneratedKeys="true"> insert into `user` values (#{id},#{username},#{password},#{age}) </insert> </mapper>
-
将
mapper
注册到mybatis-config
配置文件中<!--注册项目中mapper.xml配置--> <mappers> <mapper resource="com/ibear/mapper/UserDao.xml"/> </mappers>
-
测试
public class TestMybatis { public static void main(String[] args) throws IOException { //读取mybatis-config.xml InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); //创建mybatis核心对象SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //获取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //获取DAO对象 UserDao userDao = sqlSession.getMapper(UserDao.class); try { User user = new User(); user.setUsername("leehom"); user.setPassword("123"); user.setAge(22); int count = userDao.save(user); System.out.println("影响的条数:" + count); //数据库当前保存这条记录的id System.out.println("本次所添加记录的id:" + user.getId()); sqlSession.commit(); //提交事务 } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); //提交事务 } finally { sqlSession.close(); //释放资源 } } }
Mybatis的CRUD
-
UserDao.java
public interface UserDao { //保存用户 int save(User user); //更新用户 int update(User user); //删除操作 int delete(Integer id); //查询所有 List<User> queryAll(); //查询一个(基于ID) User queryByID(Integer id); //模糊查询like(`%国%`) List<User> queryLikeByUsername(String username); //分页查询 //startIndex:起始位置的索引 pageSize:每页显示记录数 List<User> queryByPage(@Param("start") Integer startIndex,@Param("rows") Integer pageSize); //查询总条数 Long queryTotalCounts(); }
-
UserDao.xml
(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文件是对哪个DAO接口的实现 全限定名:包.类 --> <mapper namespace="com.ibear.dao.UserDao"> <!--保存 insert:插入操作 id:接口中对应的方法名 parameterType:和接口中对应方法的参数类型一致 -> 全限定名:包.类 (#{id},#{username},#{password},#{age}): 需要与数据库列名一致,顺序也要一致 useGeneratedKeys="true":使用数据库的id自动生成策略(加不加都行,此策略只支持mysql) keyProperty="id":主键属性:当使用数据库主键自动生成策略时,将自动返回生成的id --> <insert id="save" parameterType="com.ibear.entity.User" keyProperty="id" useGeneratedKeys="true"> insert into `user` values (#{id}, #{username}, #{password}, #{age}) </insert> <!--修改--> <update id="update" parameterType="com.ibear.entity.User"> update `user` <set> <if test="username!=null and username!=''"> username=#{username}, </if> <if test="password!=null and password!=''"> password=#{password}, </if> <if test="age!=null and age!=''"> age=#{age}, </if> </set> where id=#{id} </update> <!--删除--> <delete id="delete" parameterType="Integer"> delete from `user` where id = #{id} </delete> <!--查询所有--> <!-- sql标签:用户sql片段的复用 id:相当于给sql标签中内容定义一个唯一的标识 include:引入sql标签 userQuery:被引入标签的名称 --> <sql id="userQuery"> id, username, password, age </sql> <select id="queryAll" resultType="com.ibear.entity.User"> select <include refid="userQuery"/> from `user` </select> <!--查询一个(基于ID)--> <select id="queryByID" parameterType="Integer" resultType="com.ibear.entity.User"> select <include refid="userQuery"/> from `user` where id=#{id} </select> <!--模糊查询like(`%国%`)--> <select id="queryLikeByUsername" parameterType="String" resultType="com.ibear.entity.User"> select <include refid="userQuery"/> from `user` where username like concat('%',#{username},'%') </select> <!--分页查询--> <!--多个参数时不用写parameterType--> <select id="queryByPage" resultType="com.ibear.entity.User"> select <include refid="userQuery"/> from `user` limit #{startIndex},#{pageSize} </select> <!--查询总条数--> <select id="queryTotalCounts" resultType="Long"> select count(id) from `user` </select> </mapper>
-
mybatis-config.xml
(注册配置)<!--注册项目中mapper.xml配置--> <mappers> <mapper resource="com/ibear/mapper/UserDao.xml"/> </mappers>
-
封装
MybatisUtils
工具类public class MybatisUtil { private static SqlSessionFactory sqlSessionFactory; //静态代码块 :类加载的时候执行;只执行一次 static { //读取mybatis-config.xml配置文件 InputStream is = null; try { is = Resources.getResourceAsStream("mybatis-config.xml"); //创建mybatis核心对象SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } //提供sqlSession public static SqlSession getSqlSession() { //获取sqlSession,执行sql语句 return sqlSessionFactory.openSession(); } //关闭sqlSession public static void close(SqlSession sqlSession) { sqlSession.close(); } }
-
test
测试public class TestCRUD { //保存操作 @Test public void save() throws IOException { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { //获取DAO对象 UserDao userDao = sqlSession.getMapper(UserDao.class); User user = new User(); user.setUsername("成龙"); user.setPassword("123"); user.setAge(22); int count = userDao.save(user); System.out.println("影响的条数:" + count); //数据库当前保存这条记录的id System.out.println("本次所添加记录的id:" + user.getId()); sqlSession.commit(); //提交事务 } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); //提交事务 } finally { MybatisUtil.close(sqlSession); //释放资源 } } //更新操作 //如果需要实现"只修改想修改的,不将未修改的值赋为null";需要使用动态sql。 @Test public void update() throws IOException { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { //获取DAO对象 UserDao userDao = sqlSession.getMapper(UserDao.class); User user = new User(); user.setId(26); user.setUsername("擎天柱"); user.setAge(1234); userDao.update(user); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } finally { MybatisUtil.close(sqlSession); } } //删除操作 @Test public void delete() throws IOException { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { //获取DAO对象 UserDao userDao = sqlSession.getMapper(UserDao.class); userDao.delete(27); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } finally { MybatisUtil.close(sqlSession); } } //查询所有(查询不需要操作事务) @Test public void queryAll() { SqlSession sqlSession = MybatisUtil.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> users = userDao.queryAll(); users.forEach(user -> System.out.println(user)); MybatisUtil.close(sqlSession); } //查询一个(基于ID) @Test public void queryByID() { SqlSession sqlSession = MybatisUtil.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); User user = userDao.queryByID(1); System.out.println(user); MybatisUtil.close(sqlSession); } //模糊查询like(`%国%`) @Test public void queryLikeByUsername() { SqlSession sqlSession = MybatisUtil.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> users = userDao.queryLikeByUsername("国"); users.forEach(user -> System.out.println(user)); MybatisUtil.close(sqlSession); } //分页查询 @Test public void queryByPage() { SqlSession sqlSession = MybatisUtil.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> users = userDao.queryByPage(0, 3); users.forEach(user -> System.out.println(user)); MybatisUtil.close(sqlSession); } //查询总条数 @Test public void queryTotalCounts() { SqlSession sqlSession = MybatisUtil.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); Long counts = userDao.queryTotalCounts(); System.out.println("总记录数:" + counts); MybatisUtil.close(sqlSession); } }
注意事项
-
parameterType为包装类时,可以避免传入参数为“null”导致的报错。
-
传入多个参数时,parameterType不用写。
<!--根据用户名和年龄查询--> <select id="findByNameAndAge" resultType="com.ibear.entity.Account"> select * from `user` where username = #{param 1} and age = #{param 2} </select>
-
resultType
&resultMap
的区别- 两者都是对数据库中的返回结果进行封装
- resultType 只能封装简单类型的对象
- 简单类型对象:对象中没有对象类型的属性
- resultMap 可以封装复杂类型的对象
- 多用于处理库表关联关系(一对一、一对多、多对多)
-
#{}
和${}
的区别-
#{}是预编译处理
- Mybatis在处理#{}时,会将sql中的
#{}
替换成?
号,调用PreparedStatement的set方法来赋值。
- Mybatis在处理#{}时,会将sql中的
-
${}是字符串替换
- Mybatis在处理
时
,
就
是
把
‘
{}时,就是把`
时,就是把‘{}
替换成
变量的值`。
- Mybatis在处理
时
,
就
是
把
‘
{}时,就是把`
时,就是把‘{}
使用#{}可以有效防止SQL注入,提高系统的安全性。
-
多表联查
- 一对一
- 一对多
- 多对多
一对一
外键可以放在任意一方
-
建表
t_person
&t_info
create table t_person( id int(6) primary key auto_increment, name varchar(40), age int(3), cardno varchar(18) references t_info(cardno) ); create table t_info( id int(6) primary key auto_increment, cardno varchar(18), address varchar(100) );
-
实现实体类entity
Info
@Data @AllArgsConstructor @NoArgsConstructor public class Info { private Integer id; private String cardno;//身份证号 private String address;//地址 }
Person
@Data @AllArgsConstructor @NoArgsConstructor public class Person { private Integer id; private String name; private Integer age; private String cardno; //外键信息 private Info info; //关系属性 }
-
添加方法
InfoDao
public interface InfoDao { //保存 void save(Info info); }
PersonDao
public interface PersonDao { //保存 void save(Person person); //查询所有 List<Person> queryAll(); }
-
mapper
<mapper namespace="com.ibear.dao.InfoDao"> <!--保存--> <insert id="save" parameterType="com.ibear.entity.Info" keyProperty="id" useGeneratedKeys="true"> insert into `t_info` values (#{id}, #{cardno}, #{address}) </insert> </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"> <mapper namespace="com.ibear.dao.PersonDao"> <!--保存--> <insert id="save" parameterType="com.ibear.entity.Person" keyProperty="id" useGeneratedKeys="true"> insert into `t_person` values (#{id}, #{name}, #{age}, #{cardno}) </insert> <!--查询所有--> <!--用于处理结果封装--> <resultMap id="personMap" type="com.ibear.entity.Person"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="age" property="age"/> <result column="cardno" property="cardno"/> <!--处理一对一 association:用于处理一对一关联关系标签 property:用于书写封装的关系属性名 javaType:关系属性的java类型 --> <association property="info" javaType="com.ibear.entity.Info"> <id column="iid" property="id"/> <result column="icardno" property="cardno"/> <result column="address" property="address"/> </association> </resultMap> <select id="queryAll" resultMap="personMap"> select p.id,p.name,p.age,p.cardno, i.id iid,i.cardno icardno,i.address from `t_person` p left join `t_info` i on p.cardno = i.cardno </select> </mapper>
-
注册mapper配置
<!--注册项目中mapper.xml配置--> <mappers> <!--身份信息--> <mapper resource="com/ibear/mapper/InfoDao.xml"/> <!--用户信息--> <mapper resource="com/ibear/mapper/PersonDao.xml"/> </mappers>
-
test测试
TestInfoDao
public class TestInfoDao { @Test public void save() { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { InfoDao infoDao = sqlSession.getMapper(InfoDao.class); Info info = new Info(); info.setCardno("123456789123456789"); info.setAddress("北京朝阳区"); infoDao.save(info); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } finally { MybatisUtil.close(sqlSession); } } }
TestPersonDao
public class TestPersonDao { //保存用户信息 @Test public void save() { SqlSession sqlSession = MybatisUtil.getSqlSession(); try { PersonDao personDao = sqlSession.getMapper(PersonDao.class); Person person = new Person(); person.setName("张三"); person.setAge(18); person.setCardno("123456789123456789"); personDao.save(person); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } finally { MybatisUtil.close(sqlSession); } } //查询所有用户信息 @Test public void queryAll() { SqlSession sqlSession = MybatisUtil.getSqlSession(); PersonDao personDao = sqlSession.getMapper(PersonDao.class); personDao.queryAll().forEach(person -> { System.out.println("当前用户信息:" + person); }); MybatisUtil.close(sqlSession); } }
一对多
外键最好放在多的一方
-
建表
t_dept
&t_emp
-- 部门表 create table t_dept( id int(6) primary key auto_increment, name varchar(40) ); -- 员工表 create table t_emp( id int(6) primary key auto_increment, name varchar(40), age int(3), bir timestamp, deptid int(6) references t_dept(id) );
-
创建实体类
Dept
@Data @AllArgsConstructor @NoArgsConstructor public class Dept { private Integer id; private String name; private List<Emp> emps;//关系属性 }
Emp
@Data @AllArgsConstructor @NoArgsConstructor public class Emp { private Integer id; private String name; private Integer age; private Date bir; }
-
Dao
public interface DeptDao { //查询所有部门并将每个部门的员工信息查询出来 List<Dept> queryAll(); }
-
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"> <mapper namespace="com.ibear.dao.DeptDao"> <resultMap id="deptMap" type="com.ibear.entity.Dept"> <id column="id" property="id"/> <result column="name" property="name"/> <!-- collection:用于处理"一对多"时的标签 property:用于封装关系属性名 javaType:关系属性类型 ofType:用于书写关系属性类型中泛型的类型 --> <collection property="emps" javaType="list" ofType="com.ibear.entity.Emp"> <id column="eid" property="id"/> <result column="ename" property="name"/> <result column="age" property="age"/> <result column="bir" property="bir"/> </collection> </resultMap> <select id="queryAll" resultMap="deptMap"> select d.id,d.name, e.id eid,e.name ename,e.age,e.bir from t_dept d left join t_emp e on d.id = e.deptid </select> </mapper>
-
注册
<mappers> <mapper resource="com/ibear/mapper/DeptDao.xml"/> </mappers>
-
测试
public class TestDeptDao { //查询所有部门信息 @Test public void queryAll() { SqlSession sqlSession = MybatisUtil.getSqlSession(); DeptDao deptDao = sqlSession.getMapper(DeptDao.class); deptDao.queryAll().forEach(dept -> { System.out.println("部门信息:" + dept); dept.getEmps().forEach(emp -> { System.out.println(" 员工信息:" + emp); System.out.println("=============="); }); }); MybatisUtil.close(sqlSession); } }
多对一
-
实体类Emp添加关系属性
@Data @AllArgsConstructor @NoArgsConstructor public class Emp { private Integer id; private String name; private Integer age; private Date bir; private Dept dept;//关系属性 }
-
EmpDao
public interface EmpDao { //查询所有员工并将每个员工的部门信息查询出来 List<Emp> queryAll(); }
-
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"> <mapper namespace="com.ibear.dao.EmpDao"> <resultMap id="empMap" type="com.ibear.entity.Emp"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="age" property="age"/> <result column="bir" property="bir"/> <!-- association:用于处理"一对一"时的标签 property:用于封装关系属性名 javaType:关系属性类型 ofType:用于书写关系属性类型中泛型的类型 --> <association property="dept" javaType="com.ibear.entity.Dept"> <id column="did" property="id"/> <result column="dname" property="name"/> </association> </resultMap> <select id="queryAll" resultMap="empMap"> select e.id, e.name, e.age, e.bir, d.id did, d.name dname from t_emp e left join t_dept d on e.deptid = d.id </select> </mapper>
-
注册
<mappers> <mapper resource="com/ibear/mapper/EmpDao.xml"/> </mappers>
-
测试
public class TestEmpDao { //查询所有部门信息 @Test public void queryAll() { SqlSession sqlSession = MybatisUtil.getSqlSession(); EmpDao empDao = sqlSession.getMapper(EmpDao.class); empDao.queryAll().forEach(emp -> { System.out.println("员工信息:" + emp + "部门信息:" + emp.getDept()); }); MybatisUtil.close(sqlSession); } }
多对多
-
建表
-- 学生表 create table t_student( id int(6) primary key auto_increment, name varchar(6) ); -- 课程表 create table t_course( id int(6) primary key auto_increment, name varchar(6) ); -- 中间表 create table t_student_course( id int(6) primary key auto_increment, sid int(6) references t_student(id), cid int(6) references t_course(id) );
-
创建实体类
Student
@Data @AllArgsConstructor @NoArgsConstructor public class Student { private Integer id; private String name; private List<Course> course;//关系属性 }
Course
@Data @AllArgsConstructor @NoArgsConstructor public class Course { private Integer id; private String name; private List<Student> student;//关系属性 }
-
Dao
public interface StudentDao { //根据id查询 Student queryByID(Integer id); }
-
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"> <mapper namespace="com.ibear.dao.StudentDao"> <resultMap id="studentMap" type="com.ibear.entity.Student"> <id column="id" property="id"/> <result column="name" property="name"/> <!--关系属性--> <collection property="course" javaType="list" ofType="com.ibear.entity.Course"> <id column="cid" property="id"/> <result column="cname" property="name"/> </collection> </resultMap> <select id="queryByID" parameterType="Integer" resultMap="studentMap"> select s.id, s.name, c.id cid, c.name cname from t_student s left join t_student_course sc on s.id = sc.sid left join t_course c on sc.cid = c.id where s.id = #{id} </select> </mapper>
-
注册
<mappers> <!--课程信息--> <mapper resource="com/ibear/mapper/CourseDao.xml"/> </mappers>
-
测试
public class TestStudentDao { //根据id查询学生信息 @Test public void queryByID() { SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); Student student = studentDao.queryByID(1); System.out.println("学生信息:" + student); student.getCourse().forEach(course -> { System.out.println("课程信息:" + course.getName()); }); MybatisUtil.close(sqlSession); } }
逆向工程 - MBG
MBG:MyBatis Generator
(MyBatis的逆向工程)
MyBatis框架需要:实体类
、Mapper接口
、Mapper.xml
这三个组件。
传统开发需要开发者手动创建上面三个组件,但是逆向工程可以帮助自动创建这三个组件,减轻开发者的工作量。
使用方法
-
新建Maven工程,
pom.xml
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.7</version> </dependency> </dependencies>
-
创建 MBG 配置文件:generatorConfig.xml
MyBatis延迟加载
什么是延迟加载?
延迟加载也称为懒加载,使用延迟加载可以提高程序的运行效率。
MyBatis缓存
什么是MyBatis缓存?
使用缓存可以减少java应用与数据库的交互次数,从而提升程序的运行效率。
缓存分类
一级缓存
- SqlSession级别,默认开启,不能关闭。
操作数据库时需要创建SqlSession对象,在对象中有一个HashMap用于存储缓存数据,不同的SqlSession之间缓存数据区域互不影响。
一级缓存的作用域是SqlSession范围的,当同一个SqlSession中执行两次相同的SQL语句时,第一次执行完后会将数据保存到缓存中,第二次查询时会直接从缓存中获取。
需要注意的是:如果SqlSession执行了DML操作(insert,update,delete),MyBatis必须将缓存清空以保证数据的准确性。
二级缓存
- Mapper级别,默认关闭,可以开启。
MyBatis动态SQL
if
– 只有当<if>
标签内的条件满足时,才会将<if>
标签的内容拼接到sql语句中。
where
– <where>
后面不可以接sql语句
<select id="findUser" resultType="com.ibear.entity.User">
select * from `user`
<where>
<if test="id!=null and id!=''">
id = #{id}
</if>
<if test="name!=null and name!=''">
and name = #{name}
</if>
</where>
</select>
set
–<set>
与<where>
类似,后面可以拼接sql语句。
<update id="updateUser">
update `user`
<set>
<if test="name!=null and name!=''">
name = #{name},
</if>
<if test="age!=null and age!=''">
age = #{age}
</if>
</set>
where id = #{id}
</update>
choose
– 类似java中的switch;不管满不满足条件,先执行一次。
<select id="findUser" resultType="com.ibear.entity.User">
select * from `user`
<choose>
<when test="id!=null and id!='' and name!=null and name!=''">
id = #{id} and name = #{name}
</when>
<when test="id!=null and id!=''">
id = #{id}
</when>
<otherwise>
name = #{name}
</otherwise>
</choose>
</select>
foreach
– 可以遍历List、Map、Array
collection
:指定需要遍历的元素item
:遍历之后的每一项separator
:定义foreach里面语句的分隔符index
:map中代表key,数组中代表索引。
<select id="findAll" resultType="com.ibear.entity.User">
select * from `user` where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
<insert id="batchInsertUser">
insert into `user`(id,name,age)
values
<foreach collection="users" item="user" separator=",">
(#{user.id},#{user.name},#{user.age})
</foreach>
</insert>
<update id="updateUser">
update `user`
<set>
<foreach collection="map" item="val" index="key" separator=",">
${key}=#{val}
</foreach>
</set>
where id = #{id}
</update>
bind
– 在标签内创建一个变量,提前预处理好变量,再放进语句内拼接;常用于模糊查询。
<select id="findUserById" resultType="com.ibear.entity.User">
<bind name="userName" value="name+'%'"/>
select * from `user` where name = #{userName}
</select>
参考文献