MyBatis
MyBatis快速入门
MyBatis中文网文档:https://mybatis.org/mybatis-3/zh/index.html
开发步骤:
①添加MyBatis的坐标和mysql的坐标,即安装。
②创建数据表
③编写实体类
④编写映射文件
⑤编写核心文件
⑥编写测试类
安装
要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。
如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:
mybatis依赖
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
mysql依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
创建数据表
数据表test如下图:

编写实体类Test
package org.lowell.mybatis;
public class Test {
private Integer id;
private String name;
private Integer age;
private String gender;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Test{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
创建持久层的dao接口
定义数据的操作方法
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.List;
// 接口,操作test表
public interface TestDao {
// 查询test表的所有数据
public List<Test> selectTests();
}
sql映射文件
sql映射文件就是mybatis使用的配置文件。
作用:用来写sql语句的。一般一个表一个sql映射文件。该文件就是一个xml文件。
sql映射文件在接口所在目录,文件名称和接口类一致。
<?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="org.lowell.dao.TestDao">
<select id="selectTests" resultType="org.lowell.mybatis.Test">
select * from Test order by id
</select>
</mapper>
<!--
sql映射文件:写sql语句的,mybatis会执行sql
1.指定约束文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd
作用:限制、检查在当前文件中出现的标签,属性必须符合mybatis的要求。
2.mapper是当前文件的跟标签
3.namespace:命名空间,唯一值,可以是自定义字符串
要求:一般都使用dao接口的全限定名称
4.在此xml文件中可以使用特定标签,表示数据库的特定操作,
如:<select>是查询、<update>更新、<delete>删除、<insert>插入
5.id:要执行的sql语句的唯一标识,mybatis会使用这个id值来找到对应的sql语句。
可以自定义,但要求使用接口中的方法名称。
6.resultType:表示sql语句执行后,得到的结果集的类型,遍历这个类型得到java对象的类型。
写类型的权限定名称
-->
编写核心文件
mybatis的主配置文件。一个项目就一个主配置文件。主配置文件放在resources目录下。
主配置文件的作用:提供了数据库的连接信息,和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>
<!--default和environment中的id一样,从多个地中选一个,证明使用的是那个数据库-->
<environments default="dev">
<!-- environment 一个数据库信息的配置
id 是一个唯一值,表示环境的名称
-->
<environment id="dev">
<!-- transactionManager 是mybatis的事务类型
type有两个值:JDBC(使用jdbc中的Connection对象中的commit,rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,连接数据库的
type:表示数据源类型,POOLED表示连接池
-->
<dataSource type="POOLED">
<!--数据库驱动类名-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!--连接数据库的地址-->
<!--
注意可能会报错
Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:exec (default-cli) on project 01-mybatis: Command execution failed.
则加上?serverTimezone=GMT%2B8-->
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8"/>
<!--数据库的用户名-->
<property name="username" value="root"/>
<!--数据库的密码-->
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--sql映射文件的位置,一个mapper标签指定一个文件的位置,一般来说就是一个表-->
<mapper resource="org\lowell\dao\TestDao.xml"/>
</mappers>
</configuration>
创建使用mybatis的类
通过mybatis访问数据库。
package org.lowell;
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.lowell.mybatis.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
// 访问mybatis读取test数据
// 1.定义mybatis的主配置文件名称,从类路径根开始(target/classes之后开始写)
String config = "mybatis.xml";
// 2.读取config表示的文件
InputStream inputStream = Resources.getResourceAsStream(config);
// 3.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(inputStream);
// 5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
// 6.指定要执行sql语句的标识,使用的是sql映射文件中的namespace + "." + 标签的id值
String sqlId = "org.lowell.dao.TestDao.selectTests";
// 7.执行sql语句,通过sqlId找到语句
List<Test> testList = sqlSession.selectList(sqlId);
// 8.输出结果
// testList.forEach(test -> System.out.println(test));
for (Test test : testList) {
System.out.println(test);
}
// 9.关闭
sqlSession.close();
}
}
流程描述
- 执行上述MyApp类,首先读取mybatis.xml中的数据库信息,创建连接对象,还可以拿到映射文件的位置;
- 将sqlId = "org.lowell.dao.TestDao.selectTests"传入执行sql语句的方法,可以到sql映射文件中定位到sql语句的位置。
插入操作
sql映射文件
<?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="org.lowell.dao.TestDao">
<select id="selectTests" resultType="org.lowell.mybatis.Test">
select * from test order by id
</select>
<insert id="insertTest">
insert into test values (#{id},#{name},#{age},#{gender})
</insert>
</mapper>
执行程序
注意:update、delete、insert操作,默认是不提交事务,需要手动提交事务。
也可以设置在动提交,在openSession中设置为true。
package org.lowell;
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.lowell.mybatis.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyApp {
public static void main(String[] args) throws IOException {
// 访问mybatis读取test数据
// 1.定义mybatis的主配置文件名称,从类路径根开始(target/classes之后开始写)
String config = "mybatis.xml";
// 2.读取config表示的文件
InputStream inputStream = Resources.getResourceAsStream(config);
// 3.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(inputStream);
// 5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
// 6.指定要执行sql语句的标识,使用的是sql映射文件中的namespace + "." + 标签的id值
String sqlId = "org.lowell.dao.TestDao.insertTest";
Test test = new Test();
test.setId(4);
test.setName("liuweida");
test.setAge(18);
test.setGender("男");
// 7.执行sql语句
int num = sqlSession.insert(sqlId, test);
sqlSession.commit();
// 8. 输出结果
System.out.println("插入行数:" + num);
// 9.关闭
sqlSession.close();
}
}
使用idea设置模板文件
打开Settings--》File and Code Templates--》+ 号--》输入name和后缀--》将想要保存模板的内容贴进下方窗口中,下次直接创建新文件时,就可以选择创建的模板。

MyBatis动态代理机制
如果不适用动态代理,我们需要自己去实现dao接口中的方法,我们可以直接通过调用方法来执行mybatis数据库操作,使用动态代理我们就不需要自己实现dao接口。
dao接口
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.List;
// 接口,操作test表
public interface TestDao {
// 查询test表的所有数据
public List<Test> selectTests();
// 插入数据的方法名, 返回值是一个int,表示insert之后插入数据库的数据行数
public int insertTest(Test test);
}
工具类MyBatisUtils
package org.lowell.utils;
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.IOException;
import java.io.InputStream;
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
String config = "mybatis.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(config);
factory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
SqlSession sqlSession = factory.openSession();
return sqlSession;
}
}
执行调用文件
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理, 获取对应Dao接口的代理对象
TestDao dao = sqlSession.getMapper(TestDao.class);
Test test = new Test();
test.setId(9);
test.setName("花无缺");
test.setAge(18);
test.setGender("女");
// 通过接口对象调用接口方法
int num = dao.insertTest(test);
sqlSession.commit();
System.out.println("插入行数:" + num);
sqlSession.close();
}
}
MyBatis中传递参数
parameterType
从java代码中把数据传递到mapper文件中的sql语句。
parameterType写在mapper中的一个属性。表示dao接口方法中的参数数据类型。该参数可不填。通过反射可以查询到接口参数的类型。
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.List;
public interface TestDao {
// 查询test表的所有数据
public List<Test> selectTests();
// 查询test表的一条数据
public Test selectTestById(Integer id);
public int insertTest(Test test);
}
TestDao.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="org.lowell.dao.TestDao">
<select id="selectTests" resultType="org.lowell.mybatis.Test">
select * from test order by id
</select>
<select id="selectTestById" parameterType="java.lang.Integer" resultType="org.lowell.mybatis.Test">
select * from test where id=#{id}
</select>
<insert id="insertTest">
insert into test values (#{id},#{name},#{age},#{gender})
</insert>
</mapper>
一个简单类型的参数
简单类型:mybatis把java的基本数据类型和String、Integer等都叫做简单类型。
在mapper文件中获取一个简单类型的一个参数的值,使用#{任意字符}
<select id="selectTestById" parameterType="java.lang.Integer" resultType="org.lowell.mybatis.Test">
select * from test where id=#{id}
</select>
一个#{参数},代表了jdbc中的一个?占位符。
多个参数-@Param
语法:
// 接口
public Test selectMultiParam(@Param("myName") String name, @Param("myAge") Integer age);
//
sql映射文件
<select id="selectMultiParam" resultType="org.lowell.mybatis.Test">
select * from test where name=#{myName} or age=#{myAge}
</select>
多个参数-使用对象
多个参数使用java对象的属性值,作为参数的实际值。
语法:#{属性名,javaType=类型名称,jdbcType=数据类型}
-
javaType:指java中属性数据类型
-
jdbcType:在数据库中的数据类型
#{paramName, javaType=java.lang.String, jdbcType=VARCHAR}
简化方法:#{属性名},javaType和jdbcType的值mybatis反射可以获取,不是必须提供。
dao接口层
public List<Test> selectMultiObject(Test test);
java程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
Test myTest = new Test();
myTest.setName("lowell");
myTest.setAge(18);
List<Test> tests = dao.selectMultiObject(myTest);
for (Test test : tests) {
System.out.println(test.getName());
}
sqlSession.close();
}
}
sql映射文件
<select id="selectMultiObject" resultType="org.lowell.mybatis.Test">
<!--name和age都是属性名称-->
select * from test where name=#{name} or age=#{age}
</select>
多个参数-按位置
语法:
mybatis3.4之前使用 #{0},#{1}等
mybatis3.4之后使用#{arg0},#{arg1}
接口
public List<Test> selectMultiPosition(String name, Integer age);
sql映射文件
<select id="selectMultiPosition" resultType="org.lowell.mybatis.Test">
select * from test where name=#{arg0} or age=#{arg1}
</select>
java程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
List<Test> tests = dao.selectMultiPosition("lowell", 18);
for (Test test : tests) {
System.out.println(test.getName());
}
sqlSession.close();
}
}
多个参数-使用Map
语法:
dao持久层文件
public List<Test> selectMultiMap(Map<String, Object> map);
java执行程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
Map<String, Object> data = new HashMap<>();
data.put("myname","lowell");
data.put("age",18);
List<Test> tests = dao.selectMultiMap(data);
for (Test test : tests) {
System.out.println(test.getName());
}
sqlSession.close();
}
}
sql映射文件
<select id="selectMultiMap" resultType="org.lowell.mybatis.Test">
select * from test where name=#{myname} or age=#{age}
</select>
#和&符号的区别
-
使用?在sql语句中做占位用,使用prepareStatement执行sql语句
-
能够避免sql注入,更安全
- &不适用占位符,通过子字符串链接方式,使用Statement对象执行sql,效率低。
- &有sql注入的风险。
- &可以替换表名和列名,传值传什么就会使用什么。
resultType
表示结果类型
-
结果类型,值sql执行完毕之后,数据转为的java对象。
- mybatis执行sql语句,然后mybatis调用类的无参数构造方法,创建对象。
- mybatis把ResultSet(遍历)指定列值托付给同名的属性。
<select id="selectMultiMap" resultType="org.lowell.mybatis.Test"> select id,name,email,age from test </select>和下面相同
ResultSet rs = executeQuery("select id,name,email,age from test") while (rs.next()) { Test test = new Test(); // 调用类的无参数构造方法,创建对象 test.setId(rs.getInt("id")); // ResultSet(遍历)指定列值托付给同名的属性 }
类型的别名
可以放置全限定名称,也可以放置别名。推荐使用全限定名称。
第一种方式:在mybatis主配置文件中定义,使用
<typeAliases>
<!--
type:自定义类型的全限定名称
alias:别名
-->
<typeAlias type="org.lowell.mybatis.Test" alias="test"/>
</typeAliases>
在dao文件中使用别名
<select id="selectMultiMap" resultType="test">
select * from test where name=#{myname} or age=#{age}
</select>
第二种方式:在mybatis主配置文件中定义,
<typeAliases>
<!--
name:是包名,这个包中所有的类,类名就是别名(类名不区分大小写)
-->
<package name="org.lowell.mybatis"/>
</typeAliases>
在dao文件中使用
<select id="selectMultiMap" resultType="test">
select * from test where name=#{myname} or age=#{age}
</select>
推荐使用全限定名称,如果两个包中有一个名称相同的类,那么使用别名会导致不知道使用哪个类。会抛异常。
查询返回Map
注意:返回Map时,只能返回一行数据,多一行会报错。
TestDao.java接口文件
package org.lowell.dao;
import org.apache.ibatis.annotations.Param;
import org.lowell.mybatis.Test;
import java.util.List;
import java.util.Map;
public interface TestDao {
public Map<Object, Object> selectReturnMap(Integer id);
}
sql映射文件
<select id="selectReturnMap" resultType="java.util.Map">
select id,name from test where id=#{id}
</select>
java执行程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.Map;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
Map<Object, Object> map = dao.selectReturnMap(1);
System.out.println(map); // {name=lowell, id=1}
sqlSession.close();
}
}
resultMap结果映射
指定列名和java对象的属性对应关系。一般是在列名和java对象属性名不一致时使用。
-
先定义resultMap
将列id赋值给id属性。
<!--定义resultMap id:自定义名称,表示你定义的这个resultMap type:java类型的全限定名称 --> <resultMap id="testMap" type="org.lowell.mybatis.Test"> <!--列名和java属性的关系--> <!-- 主键列 column:列名 property:java对象的属性名 --> <id column="id" property="id"/> <!-- 非主键列 使用result --> <result column="name" property="name"/> <result column="age" property="age"/> </resultMap> -
使用resultMap
<select id="selectResultMap" resultMap="testMap"> select id,name,age,gender from test </select> -
java文件中使用
package org.lowell; import org.apache.ibatis.session.SqlSession; import org.lowell.dao.TestDao; import org.lowell.mybatis.Test; import org.lowell.utils.MyBatisUtils; import java.io.IOException; import java.util.List; public class MyApp { public static void main(String[] args) throws IOException { SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 使用mybatis的动态代理 TestDao dao = sqlSession.getMapper(TestDao.class); List<Test> tests = dao.selectResultMap(); for (Test test : tests) { System.out.println(test.getName()); } sqlSession.close(); } }列名与java对象属性名不一致的情况,可以使用resultMap解决,还可以使用别名的方式解决。
<select id="selectTest02" resultType="org.lowell.mybatis.Test02"> select id as myId, name as myName, age as myAge from test </select>
模糊查询like
第一种方式
将模糊查询字符串传入到sql语句
dao文件
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.List;
public interface TestDao {
public List<Test> selectLike(String name);
}
sql映射文件
<select id="selectLike" resultType="org.lowell.mybatis.Test">
select * from test where name like #{name}
</select>
java执行程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
List<Test> tests = dao.selectLike("l%");
for (Test test : tests) {
System.out.println(test.getName());
}
sqlSession.close();
}
}
第二种方式
在sql映射文件中拼接like内容
dao文件
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.List;
public interface TestDao {
public List<Test> selectLike(String name);
}
sql映射文件
<select id="selectLike" resultType="org.lowell.mybatis.Test">
select * from test where name like #{name} "%"
</select>
java执行程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
List<Test> tests = dao.selectLike("l");
for (Test test : tests) {
System.out.println(test.getName());
}
sqlSession.close();
}
}
动态sql
sql内容是变化的,可以根据条件获取到不同的sql语句,主要是where部分发生变化。
动态sql实现,使用的是mybatis提供的标签,
动态sql要使用java对象作为参数。
if标签
用来判断条件的。语法如下:
<if test="使用参数java对象属性值作为判断条件,语法:属性=xxx">
dao文件
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.List;
public interface TestDao {
public List<Test> selectIf(Test test);
}
sql映射文件
<select id="selectIf" resultType="org.lowell.mybatis.Test">
<!--使用1=1是为了保证第一个if不成立时防止出现错误
如果第一个if不成立,那么select * from test where and age > ?会报错。
如果添加1=1,则select * from test where 1=1 and age > ?语句正确。
-->
select * from test where 1=1
<if test="name != null and name != '' ">
name=#{name}
</if>
<if test="age > 18">
and age > #{age}
</if>
</select>
java使用文件
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
Test test = new Test();
test.setName("lowell");
test.setAge(17);
// 动态sql要使用java对象作为参数。
List<Test> tests = dao.selectIf(test);
for (Test test1 : tests) {
System.out.println("-----------" + test1 + "----------");
}
sqlSession.close();
}
}
where标签
用来包含多个<where>会自动增加一个where关键字,并去除if中多余的and和or等。
dao文件
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.List;
public interface TestDao {
public List<Test> selectIf(Test test);
}
sql映射文件
<select id="selectIf" resultType="org.lowell.mybatis.Test">
select * from test
<where>
<if test="name != null and name != '' ">
name=#{name}
</if>
<if test="age > 18">
and age > #{age}
</if>
</where>
</select>
java执行程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
Test test = new Test();
test.setAge(17);
List<Test> tests = dao.selectIf(test);
for (Test test1 : tests) {
System.out.println("-----------" + test1 + "----------");
}
sqlSession.close();
}
}
foreach标签
用于循环java中的数组和list集合的。主要用于在sql的in语句中。
参数为非对象形式
dao接口文件
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.ArrayList;
import java.util.List;
public interface TestDao {
public List<Test> selectInt(ArrayList<String> arrayList);
}
sql映射文件
<select id="selectInt" resultType="org.lowell.mybatis.Test">
select * from test where name in
<!--
collection:表示接口中方法参数的类型。如果是数组使用array,如果是list集合使用list
item:自定义的,表示数组和集合的成员的变量
open:循环开始时的字符
close:循环结束时的字符
separator:集合成员之间的分隔符
-->
<foreach collection="list" item="myName" open="(" close=")" separator=",">
#{myName}
</foreach>
</select>
java执行程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("lowell");
arrayList.add("xxx");
arrayList.add("liuweida");
List<Test> tests = dao.selectInt(arrayList);
for (Test test1 : tests) {
System.out.println("-----------" + test1 + "----------");
}
sqlSession.close();
}
}
参数为对象
dao接口文件
package org.lowell.dao;
import org.lowell.mybatis.Test;
import java.util.ArrayList;
import java.util.List;
public interface TestDao {
public List<Test> selectInt(ArrayList<Test> arrayList);
}
sql映射文件
<select id="selectInt" resultType="org.lowell.mybatis.Test">
select * from test where name in
<!--
collection:表示接口中方法参数的类型。如果是数组使用array,如果是list集合使用list
item:自定义的,表示数组和集合的成员的变量
open:循环开始时的字符
close:循环结束时的字符
separator:集合成员之间的分隔符
-->
<foreach collection="list" item="myName" open="(" close=")" separator=",">
#{myName.name}
</foreach>
</select>
java执行程序
package org.lowell;
import org.apache.ibatis.session.SqlSession;
import org.lowell.dao.TestDao;
import org.lowell.mybatis.Test;
import org.lowell.utils.MyBatisUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 使用mybatis的动态代理
TestDao dao = sqlSession.getMapper(TestDao.class);
ArrayList<Test> arrayList = new ArrayList<>();
Test test = new Test();
test.setName("lowell");
arrayList.add(test);
test = new Test();
test.setName("xxx");
arrayList.add(test);
List<Test> tests = dao.selectInt(arrayList);
for (Test test1 : tests) {
System.out.println("-----------" + test1 + "----------");
}
sqlSession.close();
}
}
动态sql代码片段
<sql></sql>标签用于定义SQL片段,以便其他SQL标签可以复用。
-
定义代码片段
<sql id="自定义名称(唯一)"> // sql语句,表名,字段等。 </sql> -
使用代码片段
<include refid="定义时自定义名称(唯一)"/>
示例:
<?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="org.lowell.dao.TestDao">
<!--定义sql的片段-->
<sql id="testSelect">
select * from test
</sql>
<select id="selectInt" resultType="org.lowell.mybatis.Test">
<include refid="testSelect"/> where name in
<foreach collection="list" item="myName" open="(" close=")" separator=",">
#{myName.name}
</foreach>
</select>
</mapper>
数据库的属性配置文件
把数据库的配置信息单独放到一个文件中,和mybatis主配置文件分开。便于修改保存和处理多个数据库的信息。
-
在resources目录中定义一个属性配置文件,xxx.properties,例如:test.properties。在属性配置文件中定义数据的格式是:key=value。key使用
.做多级分隔。jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8 jdbc.username=root jdbc.password=root -
在mybatis主配置文件中,使用
<property>指定文件的位置。<?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="jdbc.properties" /> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <typeAliases> <package name="org.lowell.mybatis"/> </typeAliases> <environments default="dev"> <environment id="dev"> <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> <!--sql映射文件的位置,一个mapper标签指定一个文件的位置,一般来说就是一个表--> <mapper resource="org\lowell\dao\TestDao.xml"/> </mappers> </configuration>
指定多个mapper文件
第一种方式
<mappers>
<!--sql映射文件的位置,一个mapper标签指定一个文件的位置,一般来说就是一个表-->
<mapper resource="org\lowell\dao\TestDao.xml"/>
<mapper resource="org\lowell\dao\StudentDao.xml"/>
</mappers>
第二种方式
<mappers>
<!--
name:xml文件,sql映射文件所在的包名,这个包中所有xml文件一次性都加载给mybatis
使用package的条件:
1. mapper名称需要和接口名称一致,区分大小写
2. mapper文件和dao接口需要在同一目录
-->
<package name="org.lowell.dao"/>
</mappers>
PageHelper
PageHelper用于做数据分页。
-
先在pom.xml配置PageHelper的依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.2.0</version> </dependency> -
加入plugin,在mybatis的主配置文件中。
在
<environments default="dev">之前加入<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins> -
dao接口
package org.lowell.dao; import org.lowell.mybatis.Test; import java.util.List; public interface TestDao { public List<Test> selectAll(); } -
sql映射文件
<select id="selectAll" resultType="org.lowell.mybatis.Test"> select * from test order by id </select> -
java执行文件
package org.lowell; import com.github.pagehelper.PageHelper; import org.apache.ibatis.session.SqlSession; import org.lowell.dao.TestDao; import org.lowell.mybatis.Test; import org.lowell.utils.MyBatisUtils; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class MyApp { public static void main(String[] args) throws IOException { SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 使用mybatis的动态代理 TestDao dao = sqlSession.getMapper(TestDao.class); // 加入分页 // pageNum:从多少页开始 // pageSize:一页有多少数据 PageHelper.startPage(1,3); List<Test> tests = dao.selectAll(); for (Test test1 : tests) { System.out.println("-----------" + test1 + "----------"); } sqlSession.close(); } }
配置日志功能
Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:
- SLF4J
- Apache Commons Logging
- Log4j 2
- Log4j
- JDK logging
MyBatis 内置日志工厂会基于运行时检测信息选择日志委托实现。它会(按上面罗列的顺序)使用第一个查找到的实现。当没有找到这些实现时,将会禁用日志功能。
不少应用服务器(如 Tomcat 和 WebShpere)的类路径中已经包含 Commons Logging。注意,在这种配置环境下,MyBatis 会把 Commons Logging 作为日志工具。这就意味着在诸如 WebSphere 的环境中,由于提供了 Commons Logging 的私有实现,你的 Log4J 配置将被忽略。这个时候你就会感觉很郁闷:看起来 MyBatis 将你的 Log4J 配置忽略掉了(其实是因为在这种配置环境下,MyBatis 使用了 Commons Logging 作为日志实现)。如果你的应用部署在一个类路径已经包含 Commons Logging 的环境中,而你又想使用其它日志实现,你可以通过在 MyBatis 配置文件 mybatis-config.xml 里面添加一项 setting 来选择其它日志实现。
<configuration>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
</configuration>
可选的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是实现了 org.apache.ibatis.logging.Log 接口,且构造方法以字符串为参数的类完全限定名。
你也可以调用以下任一方法来选择日志实现:
org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging();
org.apache.ibatis.logging.LogFactory.useStdOutLogging();
应该在调用其它 MyBatis 方法之前调用以上的某个方法。另外,仅当运行时类路径中存在该日志实现时,日志实现的切换才会生效。如果你的环境中并不存在 Log4J,你却试图调用了相应的方法,MyBatis 就会忽略这一切换请求,并将以默认的查找顺序决定使用的日志实现。
关于 SLF4J、Apache Commons Logging、Apache Log4J 和 JDK Logging 的 API 介绍不在本文档介绍范围内。不过,下面的例子可以作为一个快速入门。有关这些日志框架的更多信息,可以参考以下链接:
日志配置
你可以通过在包、映射类的全限定名、命名空间或全限定语句名上开启日志功能,来查看 MyBatis 的日志语句。
再次提醒,具体配置步骤取决于日志实现。接下来我们会以 Log4J 作为示范。配置日志功能非常简单:添加一个或多个配置文件(如 log4j.properties),有时还需要添加 jar 包(如 log4j.jar)。下面的例子将使用 Log4J 来配置完整的日志服务。一共两个步骤:
步骤 1:添加 Log4J 的 jar 包
由于我们使用的是 Log4J,我们要确保它的 jar 包可以被应用使用。为此,需要将 jar 包添加到应用的类路径中。Log4J 的 jar 包可以在上面的链接中下载。
对于 web 应用或企业级应用,你可以将 log4j.jar 添加到 WEB-INF/lib 目录下;对于独立应用,可以将它添加到 JVM 的 -classpath 启动参数中。
步骤 2:配置 Log4J
配置 Log4J 比较简单。假设你需要记录这个映射器的日志:
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
在应用的类路径中创建一个名为 log4j.properties 的文件,文件的具体内容如下:
# 全局日志配置
log4j.rootLogger=ERROR, stdout
# MyBatis 日志配置
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
上述配置将使 Log4J 详细打印 org.mybatis.example.BlogMapper 的日志,对于应用的其它部分,只打印错误信息。
为了实现更细粒度的日志输出,你也可以只打印特定语句的日志。以下配置将只打印语句 selectBlog 的日志:
log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE
或者,你也可以打印一组映射器的日志,只需要打开映射器所在的包的日志功能即可:
log4j.logger.org.mybatis.example=TRACE
某些查询可能会返回庞大的结果集。这时,你可能只想查看 SQL 语句,而忽略返回的结果集。为此,SQL 语句将会在 DEBUG 日志级别下记录(JDK 日志则为 FINE)。返回的结果集则会在 TRACE 日志级别下记录(JDK 日志则为 FINER)。因此,只要将日志级别调整为 DEBUG 即可:
log4j.logger.org.mybatis.example=DEBUG
但如果你要为下面的映射器 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="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
这时,你可以通过打开命名空间的日志功能来对整个 XML 记录日志:
log4j.logger.org.mybatis.example.BlogMapper=TRACE
而要记录具体语句的日志,可以这样做:
log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE
你应该会发现,为映射器和 XML 文件打开日志功能的语句毫无差别。

浙公网安备 33010602011771号