1.基本应用
1.1 导入相关jar包或者Maven引入
注意一下MySQL的版本需要和jar包对应。
mysql-connector-java-8.0.17.jar与MySQL8.0版本以上对应,5.7的与5.7 的对应
同时8.0.17需要注意driver和serverTimezone
jdbc.driver=com.mysql.cj.jdbc.Driver
?serverTimezone=UTC
1.2 定义实体类
@Data
public class Student {
private Integer id;
private String name;
private int age;
private double score;
private String time;
}
1.3数据库
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`age` int(3) DEFAULT NULL,
`score` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
1.4 定义接口和映射文件
public interface IStudentDao {
void insertStu(Student student);
}
<?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="test">
<!-- parameterType属性可以省略 -->
<insert id="insertStudent" parameterType="Student">
insert into student(name,age,score,time) values(#{name}, #{age}, #{score},#{time,jdbcType=DATE})
</insert>
</mapper>
1.5定义配置文件
<?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>
<!-- 注册DB连接四要素属性文件 -->
<properties resource="jdbc_mysql.properties"/>
<!-- 定义类型别名 -->
<typeAliases>
<!-- <typeAlias type="com.rose.beans.Student" alias="Student"/> -->
<!-- 将指定包中所有类的简单类名当作其别名 -->
<package name="com.rose.beans"/>
</typeAliases>
<!-- 配置运行环境 -->
<environments default="testEM">
<environment id="testEM">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 注册映射文件 -->
<mappers>
<mapper resource="com/rose/dao/mapper.xml"/>
</mappers>
</configuration>
1.6 定义Dao的实现类与测试
public class StudentDaoImpl implements IStudentDao {
private SqlSession sqlSession;
@Override
public void insertStu(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.insert("insertStudent", student);
sqlSession.commit();
} finally {
if(sqlSession != null) {
sqlSession.close();
}
}
}
}
public class MyTest {
private IStudentDao dao;
@Before
public void before() {
dao = new StudentDaoImpl();
}
@Test
public void testInsert() {
Student student = new Student("rose3", 23, 93.5);
dao.insertStu(student);
}
}
2.$与#的区别
#为占位符,而$为字符串拼接符
字符串拼接是将参数值直接以硬编码的方式直接拼接到了SQL语句中。字符串拼接就会引发两个问题:SQL注入问题与没有使用预编译所导致的执行效率低下的问题
3.Mapper动态代理
前面的例子中Dao接口实现类时候发现了一个问题:Dao的实现类并没有做什么实质性的工作,仅仅通过SqlSession的相关API定位到映射文件mapper中相应id的SQL语句,真正对DB进行的操作是通过Mapper的SQL完成的。
所以 Mybatis可以抛弃Dao的实现类,直接使用动态代理,无需在编写Dao的实现类。
简单的来说,通过接口名定位到映射文件
<mapper namespace="com.rose.dao.IStudentDao">
</mapper>
4.多查询条件
4.1将多个参数封装成Map
List<Student> selectStudentByMap(Map<String,object> map);
4.2 多个参数逐个接受
List<Student> selectStudentByConditions(String name,int age);
5.动态sql
动态sql用来解决查询条难吗不确定的情况;在程序运行的期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的sql语句不同。如果将每种情况分别写sql,工作量大。可以使用动态sql。
常见的动态sql标签有
public interface IStudentDao {
List<Student> selectStudentsByIf(Student student);
List<Student> selectStudentsByWhere(Student student);
List<Student> selectStudentsByChoose(Student student);
List<Student> selectStudentsByForeach(int[] ids);
List<Student> selectStudentsByForeach2(List<Integer> ids);
List<Student> selectStudentsByForeach3(List<Student> ids);
List<Student> selectStudentsBySqlFragment(List<Student> ids);
}
<mapper namespace="com.rose.dao.IStudentDao">
<select id="selectStudentsByIf" resultType="Student">
select id,name,age,score
from student
where 1 = 1
<if test="name != null and name != ''">
and name like '%' #{name} '%'
</if>
<if test="age > 0">
and age > #{age}
</if>
</select>
<select id="selectStudentsByWhere" resultType="Student">
select id,name,age,score
from student
<where>
<if test="name != null and name != ''">
and name like '%' #{name} '%'
</if>
<if test="age > 0">
and age > #{age}
</if>
</where>
</select>
<select id="selectStudentsByChoose" resultType="Student">
select id,name,age,score
from student
<where>
<choose>
<when test="name != null and name !=''">
and name like '%' #{name} '%'
</when>
<when test="age > 0">
and age > #{age}
</when>
<otherwise>
1 = 2
</otherwise>
</choose>
</where>
</select>
<select id="selectStudentsByForeach" resultType="Student">
<!-- select id,name,age,score from student where id in (1,3,5) -->
select id,name,age,score
from student
<if test="array.length > 0">
where id in
<foreach collection="array" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</if>
</select>
<select id="selectStudentsByForeach2" resultType="Student">
<!-- select id,name,age,score from student where id in (1,3,5) -->
select id,name,age,score
from student
<if test="list.size > 0">
where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</if>
</select>
<select id="selectStudentsByForeach3" resultType="Student">
<!-- select id,name,age,score from student where id in (1,3,5) -->
select id,name,age,score
from student
<if test="list.size > 0">
where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</if>
</select>
<select id="selectStudentsBySqlFragment" resultType="Student">
<!-- select id,name,age,score from student where id in (1,3,5) -->
select <include refid="selectColumns"/>
from student
<if test="list.size > 0">
where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</if>
</select>
<sql id="selectColumns">
id,name,age,score
</sql>
</mapper>
6.关联关系查询
6.1 一对多
一对多关联查询值得是查询一方的时候,同时将其所关联的多方对象也都查询出来。下面以Country与部长Minister一对多演示。
public class Country {
private Integer cid;
private String cname;
// 关联属性
private Set<Minister> ministers;
}
public class Minister {
private Integer mid;
private String mname;
}
使用resultMap collection,将多方放入 collection当中
<mapper namespace="com.rose.dao.ICountryDao">
<resultMap type="Country" id="countryMapper">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
<collection property="ministers" ofType="Minister">
<id column="mid" property="mid"/>
<result column="mname" property="mname"/>
</collection>
</resultMap>
<select id="selectCountryById" resultMap="countryMapper">
select cid,cname,mid,mname
from country,minister
where countryId=cid and cid=#{xxx}
</select>
</mapper>
6.2多对一
public class Minister {
private Integer mid;
private String mname;
// 关联属性
private Country country;
}
使用 association
<mapper namespace="com.rose.dao.IMinisterDao">
<resultMap type="Minister" id="ministerMapper">
<id column="mid" property="mid"/>
<result column="mname" property="mname"/>
<association property="country" javaType="Country">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
</association>
</resultMap>
<select id="selectMinisterById" resultMap="ministerMapper">
select mid,mname,cid,cname
from minister, country
where countryId=cid and mid=#{xxx}
</select>
</mapper>
7.缓存
7.1一级缓存
Mybatis一级查询缓存本质上基于HashMap的本地缓存,作用域是SqlSession。在同一个SqlSession中执行两次相同的sql查询语句,第一次执行完之后,会将查询结果写入到缓存中,第二次直从缓存中获取数据。不到数据库中查询。
当一个sqlsession结束后,该sqlSession中的一级查询也不存在了。mybatis默认一级缓存开启,且不能关闭。
増、删、改操作,无论是否提交sqlSession.commit(),均会清空一级查询缓存,使查询再次从DB中select。
7.2二级缓存
(1)要求涉及的实体类要实现java.io.Serializable接口
(2)mapper映射中添加 标签
<cache/>