本着一切以官方文档为准的原则,快速入门参考了官方文档给的例子
mybatis官方文档地址
目录
1 快速入门
目录结构
1.1 在项目中引入mybatis依赖包
使用maven构建的项目在pom文件中加入mybatis需要的dependency
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
1.2 mybatis全局配置文件
每一个Mybatis应用是以一个SqlSessionFactory为中心,SqlSessionFactory实例可以由SqlSessionFactoryBuilder解析xml配置文件来初始化。
全局配置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>
<!--
数据库环境配置,如果和spring整合了就不需要配了,完全交给spring管理
environments 里面可以配置多个environment default:指定采用哪个环境
-->
<environments default="development">
<environment id="development">
<!--事务管理器 JDBC类型的事务管理器-->
<transactionManager type="JDBC"/>
<!--数据源 池类型的数据源-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--管理每一张表的映射文件 -->
<mappers>
<mapper resource="mapper/PersonMapper.xml"/>
</mappers>
</configuration>
PersonMapper.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="PersonMapper">
<!--
id:sql唯一标识
paramterType : 传递给sql语句的参数
resultType: 返回数据结果的类型
#{id} : 用于接收参数的语法,如果是接收一个参数{}里面的内容任意
-->
<select id="selectPersonById" parameterType="java.lang.Integer" resultType="com.mybatisDemo.model.Person">
select * from person where id = #{id}
</select>
</mapper>
1.3 测试代码
实体类Person.class
package com.mybatisDemo.model;
public class Person {
private String name;
private Integer age;
private Integer gender;
private String addr;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
", addr='" + addr + '\'' +
'}';
}
}
数据库准备测试数据,新建person表 插入几条测试数据
1.3 测试代码
import com.mybatisDemo.model.Person;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class MybatisTest {
public static void main(String[] args) throws Exception {
//指定配置文件
String resource = "mybatis-config.xml";
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过配置文件构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
//获取SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//执行查询操作
//第一个参数:命名空间+statementId 第二个参数为传入参数 这里为人员id
Person person = sqlSession.selectOne("PersonMapper.selectPersonById", 1);
System.out.println(person);
} finally {
sqlSession.close();
}
}
}
运行结果:
以上就完成了使用mybatis实现的简单查询。
2 mybatis的CRUD
2.1 < resultMap > 标签
在上面的例子中,resultType指定为com.mybatisDemo.model.Person,此时Person实体类中的属性名和数据库person表中的字段名完全对应,此时能够将查询结果注入到Person之中。但是实际项目中往往属性名和表字段名不能完全对应,此时就需要使用< resultMap > 标签来定义对应关系。
下面例子中person表字段名变更为person_id,person_name,person_age,gender,addr
Person类属性名采用驼峰命名
package com.mybatisDemo.model;
public class Person {
private Integer personId;
private String personName;
private Integer personAge;
private Integer gender;
private String addr;
@Override
public String toString() {
return "Person{" +
"personId=" + personId +
", personName='" + personName + '\'' +
", personAge=" + personAge +
", gender=" + gender +
", addr='" + addr + '\'' +
'}';
}
}
修改PersonMapper.xml文件,使用resultMap来对应字段名称
<?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="PersonMapper">
<!--
resultMap:组装从数据库表中查询出来的实体
type:实体的数据类型
id:唯一标识
-->
<resultMap id="BaseResultMap" type="com.mybatisDemo.model.Person">
<!--
id列只有一个
column:表的字段名
property:实体类属性名
-->
<id column="person_id" property="personId"></id>
<result column="person_name" property="personName"></result>
<result column="person_age" property="personAge"></result>
<result column="gender" property="gender"></result>
<result column="addr" property="addr"></result>
</resultMap>
<!--
id:sql唯一标识
paramterType : 传递给sql语句的参数
resultType: 返回数据结果的类型
#{id} : 用于接收参数的语法,如果是接收一个参数{}里面的内容任意
-->
<select id="selectPersonById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select * from person where person_id = #{id}
</select>
</mapper>
2.2 查询列表
package com.mybatisDemo.test;
import com.mybatisDemo.model.Person;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() {
//指定配置文件
String resource = "mybatis-config.xml";
//读取配置文件
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
//通过配置文件构建SqlSessionFactory
sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void selectPersonList() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Person> personList;
try {
//查询列表
personList = sqlSession.selectList("PersonMapper.selectPersonList", 5);
for (Person person : personList) {
System.out.println(person);
}
} finally {
sqlSession.close();
}
}
}
<select id="selectPersonList" resultMap="BaseResultMap">
select * from person limit #{limit}
</select>
2.3 多个查询条件
多个查询参数的传递有两种方式:1.传递查询对象 2:传递map集合
1.传递参数对象
<!--
多个参数查询
第一种方式:传递查询对象
#{}中的内容为查询对象属性名
-->
<select id="selectPersonByCondition" parameterType="com.mybatisDemo.model.Person" resultMap="BaseResultMap">
<![CDATA[ select * from person p where p.gender = #{gender} and p.person_age < #{personAge}]]>
</select>
@Test
public void selectPersonByCondition() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Person condition = new Person();
condition.setGender(1);
condition.setPersonAge(28);
List<Person> personList = sqlSession.selectList("PersonMapper.selectPersonByCondition", condition);
for (Person person : personList) {
System.out.println(person);
}
} finally {
sqlSession.close();
}
}
2.传递map
<!--
多个参数查询
第二种方式:使用map集合
map.put(key,value) #{}中内容为map的key
-->
<select id="selectPersonByMap" parameterType="map" resultMap="BaseResultMap">
<![CDATA[ select * from person p where p.gender = #{gender} and p.person_age < #{personAge}]]>
</select>
@Test
public void selectPersonByMap() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Map<String, Object> map = new HashMap<String, Object>();
map.put("gender", 1);
map.put("personAge", 25);
List<Person> personList = sqlSession.selectList("PersonMapper.selectPersonByMap", map);
for (Person person : personList) {
System.out.println(person);
}
} finally {
sqlSession.close();
}
}
2.4 模糊查询 #{}和${}
<!--
模糊查询
${}:非预编译,使用直接拼接字符串的方式生成sql ${}中的内容必须从map或者参数对象中获得
-->
<select id="selectPersonByLike" parameterType="map" resultMap="BaseResultMap">
select * from person p where p.person_name like '%${personName}%'
</select>
@Test
public void selectPersonByLike(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Map<String, Object> map = new HashMap<String, Object>();
map.put("personName", "李");
List<Person> personList = sqlSession.selectList("PersonMapper.selectPersonByLike", map);
for (Person person : personList) {
System.out.println(person);
}
} finally {
sqlSession.close();
}
}
2.5 insert
<insert id="insertPerson" parameterType="com.mybatisDemo.model.Person">
insert into person (person_name,person_age,gender,addr) values (#{personName},#{personAge},#{gender},#{addr})
</insert>
@Test
public void insertPerson() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Person person = new Person();
person.setPersonName("宋祖英");
person.setPersonAge(29);
person.setGender(2);
person.setAddr("湖南");
sqlSession.insert("PersonMapper.insertPerson", person);
sqlSession.commit();
} finally {
sqlSession.close();
}
}
数据变更都需要调用sqlSession.commit()提交事务。
person表中主键person_id是自增的,想要在插入数据之后返回主键id,需修改PersonMapper.xml
<insert id="insertPerson" parameterType="com.mybatisDemo.model.Person">
<!--
selectKey标签用作主键返回
keyProperty:接收返回的主键的属性
order:生成主键和insert语句的顺序 mysql是after orcal 是before
resultType:返回主键的数据类型
last_insert_id() 生成主键的sql
-->
<selectKey keyProperty="personId" order="AFTER" resultType="java.lang.Integer">
select last_insert_id()
</selectKey>
insert into person (person_name,person_age,gender,addr) values (#{personName},#{personAge},#{gender},#{addr})
</insert>
2.6 delete
<!--delete sql语句中不能使用别名-->
<delete id="deletePersonById" parameterType="java.lang.Integer">
delete from person where person_id = #{personId}
</delete>
@Test
public void deletePersonById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
sqlSession.delete("PersonMapper.deletePersonById", 12);
sqlSession.commit();
} finally {
sqlSession.close();
}
}
2.7 update
<update id="updatePerson" parameterType="com.mybatisDemo.model.Person">
update person p set
p.person_name = #{personName},
p.person_age = #{personAge},
p.gender = #{gender},
p.addr = #{addr}
where
p.person_id = #{personId}
</update>
@Test
public void updatePerson() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Person person = new Person();
person.setPersonId(11);
person.setPersonName("宋祖德");
person.setPersonAge(30);
person.setGender(1);
person.setAddr("南京");
sqlSession.update("PersonMapper.updatePerson", person);
sqlSession.commit();
System.out.println(person);
} finally {
sqlSession.close();
}
}
这里存在一个问题,如果传入参数person的personName、personAge、gender、addr值为null,即我们只想修改地址信息。若使用上面的sql语句,会在数据库中把person_name、person_age、gender、addr更新为null,达不到我们想要的目的。
为了解决这个问题,我们需要用到动态sql
2.8 动态sql
2.8.1 < set > 标签 动态修改
<!--
使用<set>标签动态修改 能处理掉最后一个逗号
-->
<update id="dynamicUpdate" parameterType="com.mybatisDemo.model.Person">
update person p
<set>
<if test="personName != null">
p.person_name = #{personName},
</if>
<if test="personAge != null">
p.person_age = #{personAge},
</if>
<if test="gender != null">
p.gender = #{gender},
</if>
<if test="addr != null">
p.addr = #{addr},
</if>
</set>
where p.person_id = #{personId}
</update>
2.8.2< where > 动态查询
使用< where >标签进行动态条件组合查询 可以处理掉where后面的第一个and
<select id="dynamicSelect" parameterType="com.mybatisDemo.model.Person" resultMap="BaseResultMap">
select * from person p
<where>
<if test="personId != null">
p.person_id = #{personId}
</if>
<if test="personName != null">
and p.person_name = #{personName}
</if>
<if test="personAge != null">
and p.person_age = #{personAge}
</if>
<if test="gender != null">
and p.gender = #{gender}
</if>
<if test="addr != null">
and p.addr = #{addr}
</if>
</where>
</select>
2.9 foreach 遍历组装sql
2.9.1 in条件查询
如果我们有一条sql:SELECT * FROM person where person_id in (1,2,7,8),怎样用mybatis来完成查询?
< foreach > 可以帮助我们完成遍历传入的参数,完成sql组装:
<!--
foreach遍历集合来组装sql
map.put("ids",List or Set or 数组)
collection:在map中集合的key;
open:以某种字符开始
close: 以某种字符结尾
item: 集合中的元素
separator:以某种字符分隔
index:当前所遍历到的索引号
-->
<select id="selectPersonByIn" parameterType="map" resultMap="BaseResultMap">
select * from person p where person_id in
<foreach collection="ids" open="(" close=")" item="id" separator="," index="index">
#{id}
</foreach>
</select>
2.9.2 批量insert
例sql语句:insert into person (person_name,person_age,gender,addr) values (‘刘德华’,‘45’,‘1’,‘香港’),(‘周杰伦’,‘38’,‘1’,‘台湾’),(‘邓紫棋’,‘28’,‘2’,‘香港’)
<!--
批量插入
map.put(studentList,List<Student>)
insert into student (s_name,s_age) valus (aaa,15),(bbb,16),(ccc,20).......
-->
<insert id="insertPersonList" parameterType="map">
insert into person (person_name,person_age,gender,addr) values
<foreach collection="personList" item="p" separator=",">
(#{p.personName},#{p.personAge},#{p.gender},#{p.addr})
</foreach>
</insert>