简介
MyBatis 是一款持久层框架。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。Mybatis 使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJO(Plain Old Java Object,普通 Java 对象)映射成数据库中的记录。比传统的 JDBC 编码要简单很多。Mybatis允许开发者自由使用SQL语句,并通过API或XML配置文件进行灵活配置。
名词解释:
持久层指的是将数据存储到能长期存储的磁盘中,不会像在程序中new一个对象,程序结束后这个对象的生命周期也就相继结束了。通常在企业应用中的数据信息很重要(例如:用户的信息,订单...),所以就需要将这些数据持久化,持久化有很多种方式:写文件,存入数据库...通常我们都习惯与存储至数据库方便后期的查询等操作。
框架就是一个软件平台,其中包含了常见的功能模块和代码结构,开发者只需在此基础上进行定制和扩展即可,而无需从头开始编写全部代码。通俗来讲:框架就是一个应用程序的半成品
一、安装
如果使用的是maven项目,则将下列依赖导入pom.xml里即可
<dependencies>
//lombok
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
//mybatis
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
//mysql
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
//lombok
二、创建
1.创建配置文件mybatis.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>
<!--导入外部属性文件-->
<properties resource="database.properties"/>
<!--数据源环境信息可以自定义名-->
<environments default="development">
<environment id="development">
<!--事务管理器-->
<transactionManager type="JDBC"/>
<!--连接池-->
<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>
</environment>
</environments>
<!--映射文件-->
<mappers>
<mapper resource="com/its/mapper/UserMapper.xml"/>
</mappers>
</configuration>
2.项目结构
在java文件夹下创建相应的实体类对象,再创建要实现功能的接口,因为mybatis要将接口与相应的sql文件做相应的捆绑,但并不是捆绑关系,只不过是将xml文件作为java的实现类,所以需要将xml文件独立出来。(注意:在java中建立三级目录使用com.its.xx,而在resources中建立三级目录使用com/its/xx)
## 2.创建外部属性文件
在resources下创建database.properties用来保存配置文件(在配置文件中建议使用xx.driver防止重名)
jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql:///test
jdbc.username = root
jdbc.password = xx//数据库密码
三.简要功能
1.实现查询功能
在数据库中建立相应的user表
创建相应的实体类对象
//lombok插件
@Data
@AllArgsConstructor
@NoArgsConstructor
//链式编程
@Accessors(chain = true)
public class User {
private int id;
private String name;
private String username;
private String password;
}
在UserMapper中建立相应的功能接口
List<User> list() ;
在UserMapper.xml文件里编写相应的sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.its.mapper.UserMapper" >
<select id="list" resultType="com.its.pojo.User">
select * from user
</select>
</mapper>
再对此功能进行测试
/查询
@Test
public void list(){
//读取核心配置文件流信息
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//获取一个SqLSessionFactory数据库会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//获取连接信息
SqlSession session = sqlSessionFactory.openSession();
//加载Mapper接口
UserMapper mapper = session.getMapper(UserMapper.class);
//执行
List<User> list = mapper.list();
list.forEach(System.out::println);
}
查询结果
2.完整实现表中数据的增删改查
在UserMapper接口中定义相应的方法
public interface UserMapper {
//查整个表
List<User> list() ;
//增加
int save(User user);
//修改
int update(User user);
//删除
int delete(int id);
//根据id查数据
User queryUserById(int id);
}
在UserMapper.xml中编写相应的sql语句查询
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.its.mapper.UserMapper" >
<insert id="save" parameterType="user">
insert into user(name,username,password)
value (#{name},#{username},#{password})
</insert>
<update id="update" parameterType="com.its.pojo.User">
update user set name=#{name},username=#{username},
password=#{password} where id=#{id}
</update>
<delete id="delete" parameterType="com.its.pojo.User">
delete from user where id=#{id}
</delete>
<select id="list" resultType="com.its.pojo.User">
select * from user
</select>
<select id="queryUserById" parameterType="integer" resultType="com.its.pojo.User">
select * from user where id=#{id}
</select>
</mapper>
对这些方法进行测试(注意:在增加,修改和删除时需要对操作的数据进行提交)
public class MybatisTest {
SqlSession session;
@Before
public void init() throws IOException {
//读取核心配置文件流信息
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//获取一个SqLSessionFactory数据库会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//获取连接信息
session = sqlSessionFactory.openSession();
}
//销毁
@After
public void destory(){
session.close();
}
//查询
@Test
public void list(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list = mapper.list();
list.forEach(System.out::println);
}
//增加
@Test
public void save(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user=new User()
.setName("张三")
.setUsername("zhangsan")
.setPassword("123456");
int save = mapper.save(user);
session.commit();
System.out.println("增加成功");
}
//修改
@Test
public void update(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user=new User()
.setId(6)
.setName("张三sa")
.setUsername("zhangsanasan")
.setPassword("123");
int update = mapper.update(user);
session.commit();
System.out.println("修改成功");
}
//删除
@Test
public void del(){
UserMapper mapper = session.getMapper(UserMapper.class);
int delete = mapper.delete(5);
session.commit();
System.out.println("删除成功!");
}
//根据id查数据
@Test
public void queryUserById(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.queryUserById(6);
System.out.println(user);
}
}
3.总结
1.编写配置文件连接数据库
2.创建对象实例
3.编写mapper类和sql文件
4.进行测试
四.详细内容
<configuration>: 整个配置文件的根标签,包含了 MyBatis 的所有配置信息。
<properties>: 用于定义一些属性值,可以在其他地方引用这些属性。
<settings>: 用于配置 MyBatis 的全局设置,比如缓存、延迟加载、日志等。
<typeAliases>: 用于定义类型别名,简化类型的书写。
<typeHandlers>: 用于自定义类型处理器,处理特殊的数据类型。
<environments>: 用于配置数据库连接信息,可以配置多个环境。
<environment>: 环境标签,用于定义单个数据库连接环境。
<transactionManager>: 用于配置事务管理器。
<dataSource>: 用于配置数据源。
<mappers>: 用于配置 SQL 映射文件的位置。
<mapper>: 指定单个 SQL 映射文件的位置。
<?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>
<!--导入外部属性文件-->
<properties resource="database.properties"/>
<!-- 设置日志 -->
<!--<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>-->
<!--别名-->
<typeAliases>
<!--别名的用途就是简化实体类的写法,将原有的全限定类名替换为一个简-->
<package name="com.its.pojo"/>
</typeAliases>
<!--一级缓存
<settings>
<setting name="localCacheScope" value="SESSION"/>
</settings>-->
<!--数据源环境信息可以自定义名-->
<environments default="development">
<environment id="development">
<!--事务管理器-->
<transactionManager type="JDBC"/>
<!--连接池-->
<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>
</environment>
</environments>
<!--映射文件-->
<mappers>
<mapper resource="com/its/mapper/UserMapper.xml"/>
</mappers>
</configuration>
1.查询(单个参数查询)
<select id="selectBooksTitle" resultType="com.its.pojo.Books">
select * from books where title=#{title}
//在mybatis中单个参数可以自定义select中的参数名称,多个参数,对象就不可以自定义名称
</select>
2.查询(多个参数查询)
@Test
public void t03(){
BooksMapper mapper = session.getMapper(BooksMapper.class);
List<Books> list=mapper.selectBooksMoreParameter("活着","余华");
list.forEach(System.out::println);
}
第一种:
List<Books> selectBooksMoreParameter(String title,String author);
<select id="selectBooksMoreParameter" resultType="com.its.pojo.Books">
select * from books where title=#{param1} and author=#{param2}
</select>
- 第二种:
List<Books> selectBooksMoreParameter(String title,String author);
<select id="selectBooksMoreParameter" resultType="com.its.pojo.Books">
select * from books where title=#{arg0} and author=#{arg1}
</select>
- 第三种:
List<Books> selectBooksMoreParameter2(@Param("title") String title, @Param("author") String author);
<select id="selectBooksMoreParameter2" resultType="com.its.pojo.Books">
select * from books where title=#{title} and author=#{author}
</select>
3.“#”和”$“的区别
//$ 和 # 接收的区别: $不会预编译有SQL注入风险 #是预编译处理
@Test
public void t06(){
BooksMapper mapper = session.getMapper(BooksMapper.class);
List<Books> list=mapper.selectBooksMarkType("活着","余华");
list.forEach(System.out::println);
}
List<Books> selectBooksMarkType(@Param("title") String title, @Param("author") String author);
<select id="selectBooksMarkType" resultType="com.its.pojo.Books">
select * from books where title='${title}' and author='${author}'
</select>
4.模糊查询
//模糊查询
@Test
public void t07(){
BooksMapper mapper = session.getMapper(BooksMapper.class);
List<Books> list=mapper.selectBookslike("凡");
list.forEach(System.out::println);
}
List<Books> selectBookslike(String title);
<select id="selectBookslike" resultType="com.its.pojo.Books">
select * from books where title like concat('%',#{title},'%')
</select>
5.注解查询(不通过xml文件)
//注解模式
@Test
public void t08(){
BooksMapper mapper = session.getMapper(BooksMapper.class);
List<Books> list=mapper.selectBookslikeAnn("凡");
list.forEach(System.out::println);
}
@Select("select * from books where title like concat('%',#{title},'%')")
List<Books> selectBookslikeAnn(String title);
6.sql标签
sql元素
<sql id="employee">
id,name,position,entryTime,wage,bonus
</sql>
<select id="selectEmployeeList" resultType="com.its.pojo.Employee">
select <include refid="employee"/> from employee
</select>
动态sql
<if> 标签: 用于根据条件判断是否添加某个查询条件。
<where> 标签: 用于动态地生成 WHERE 子句,避免出现条件语句中的 "AND" 或 "OR" 开头的情况。
<foreach> 标签: 用于迭代集合,支持在 IN 条件中使用集合。
<choose> 、 <when> 和 <otherwise> 标签: 实现 switch case 的功能,根据条件选择执行。
<trim> 标签: 用于动态地修剪 SQL 语句的前缀或后缀。
<set> 标签: 用于动态地生成 SET 子句,避免出现最后一个 SET 后面多一个逗号的情况。
if标签
@Test
public void t01(){
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.selectEmployeeList("玛","保洁","");
list.forEach(System.out::println);
}
List<Employee> selectEmployeeList(@Param("name") String name, @Param("position")String position,@Param("entryTime") String date);
<select id="selectEmployeeList" resultType="com.its.pojo.Employee">
select <include refid="employee"/> from employee
<where>
<if test="name != null and name != ''">
and name like concat('%',#{name},'%')
</if>
<if test="position != null and position != ''">
and position=#{position}
</if>
<if test="entryTime != null and entryTime != ''">
and date(entryTime)=#{entryTime}//date(entryTime)忽略时分秒的处理
</if>
</where>
</select>
7.when标签
//根据工资查询指定的数据
@Test
public void t02(){
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.selectEmployeeList1("45000");
list.forEach(System.out::println);
}
List<Employee> selectEmployeeList1(String wage);
<select id="selectEmployeeList1" resultType="com.its.pojo.Employee">
select <include refid="employee"/> from employee
<where>
<choose>
<when test="wage != null and wage !=''">
wage=#{wage}
</when>
<otherwise>
wage < 10000//<为"<"的转义字符,>为">"的转义字符
</otherwise>
</choose>
</where>
</select>
8.foreach标签
//查询工资为 15000 12000 8500的人
@Test
public void t03(){
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(17000);
list1.add(18000);
list1.add(18000);
List<Employee> list = mapper.selectEmployeeList2(list1);
list.forEach(System.out::println);
}
List<Employee> selectEmployeeList2(@Param("list1") ArrayList<Integer> list1);
<select id="selectEmployeeList2" parameterType="list" resultType="com.its.pojo.Employee">
select <include refid="employee"/> from employee
<where>
wage in
//(wage,wage,wage)
<foreach collection="list1" item="wage" open="(" close=")" separator=",">
#{wage}
</foreach>
</where>
</select>
9.bind标签
<bind> 标签允许开发者在 SQL 语句中动态创建变量,并将这些变量绑定到 SQL 语句中使用。这使得 SQL 语句更加灵活和动态。
//测试bind方法-为了各个数据库统一使用的方式
@Test
public void t04(){
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.selectEmployeeList3("二");
list.forEach(System.out::println);
}
List<Employee> selectEmployeeList3(String name);
<select id="selectEmployeeList3" resultType="com.its.pojo.Employee">
select <include refid="employee"/> from employee
<bind name="dd" value="'%'+name+'%'"/>
<where>
name like #{dd}
</where>
</select>
10.关联映射
一对一
就像一个人拥有一张身份证一样,一个对象包含另一个对象的属性
案例:通过工卡ID查询工卡信息并查询打卡记录工卡mapper
//通过工卡ID查询工卡信息并查询打卡记录-工卡mapper
@Test
public void t01(){
WorkCardMapper mapper = session.getMapper(WorkCardMapper.class);
WorkCard workCard=mapper.queryWorkcardByIdAndRecord(1);
System.out.println(workCard);
}
WorkCard queryWorkcardByIdAndRecord(int id);
<select id="queryWorkcardByIdAndRecord" resultMap="queryWorkcardByIdAndRecordMap">
select * from workcard w ,record r
where w.id=r.workcard_id
and w.id=#{id}
</select>
<resultMap id="queryWorkcardByIdAndRecordMap" type="workCard">
<id column="id" property="id"/>
<result column="cw_no" property="cwNo"/>
<result column="cw_attendance" property="cwAttendance"/>
<result column="cw_entertime" property="cwEntertime"/>
<collection property="recordList" ofType="record">
<id column="record_id" property="recordId"/>
<result column="record_pos_name" property="recordPosName"/>
<result column="record_time" property="recordTime"/>
</collection>
</resultMap>
一对多
就像一个部门包含多个员工一样,一个对象包含多个另一种类型的对象。
//通过工卡ID查询工卡信息并查询打卡记录-工卡mapper
@Test
public void t01(){
WorkCardMapper mapper = session.getMapper(WorkCardMapper.class);
WorkCard workCard=mapper.queryWorkcardByIdAndRecord(1);
System.out.println(workCard);
}
WorkCard queryWorkcardByIdAndRecord(int id);
<select id="queryWorkcardByIdAndRecord" resultMap="queryWorkcardByIdAndRecordMap">
select * from workcard w ,record r
where w.id=r.workcard_id
and w.id=#{id}
</select>
<resultMap id="queryWorkcardByIdAndRecordMap" type="workCard">
<id column="id" property="id"/>
<result column="cw_no" property="cwNo"/>
<result column="cw_attendance" property="cwAttendance"/>
<result column="cw_entertime" property="cwEntertime"/>
<collection property="recordList" ofType="record">
<id column="record_id" property="recordId"/>
<result column="record_pos_name" property="recordPosName"/>
<result column="record_time" property="recordTime"/>
</collection>
</resultMap>
多对多
就像一个学生可以选择多门课程,而一门课程也可以被多个学生选择一样,两个对象互相包含对方的集合。
思想:设定中间表,用中间去关联其他两张表,将两张主表的主键分别设定为第三张表的外键
案例:*查询员工巫妖王的员工的任务有哪些并返回详细任务信息(优先员工)*
//查询员工巫妖王的员工的任务有哪些并返回详细任务信息(优先员工)
@Test
public void t02(){
TaskMapper mapper = session.getMapper(TaskMapper.class);
List<Employee> list=mapper.selectTaskByEmpName1("巫妖王");
list.forEach(System.out::println);
}
List<Employee> selectTaskByEmpName1(String name);
<select id="selectTaskByEmpName1" resultMap="selectTaskByEmpName1Map">
select e.*,t.* from employee e,employee_task et,task t
where e.id=et.emp_id
and et.emp_id=t.task_id
and e.name=#{name}
</select>
<resultMap id="selectTaskByEmpName1Map" type="employee">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="position" property="position"/>
<result column="entryTime" property="entryTime"/>
<result column="wage" property="wage"/>
<result column="bonus" property="bonus"/>
<collection property="employeeList" ofType="task">
<id column="task_id" property="taskId"/>
<result column="task_name" property="taskName"/>
<result column="task_type" property="taskType"/>
<result column="task_description" property="taskDescription"/>
<result column="task_public_time" property="taskPublicTime"/>
</collection>
</resultMap>
注:该篇mybatis笔记并未整理完全,第二版将会有更全面mybatis笔记。