mybatis 3.5
简介
mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
1)sql mapper :sql映射
可以把数据库表中的一行数据 映射为 一个java对象。即一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据。
2)Data Access Objects(DAOs):数据访问
对数据库执行增删改查。
mybatis提供了哪些功能:
- 提供了创建Connection ,Statement, ResultSet的能力,不用开发人员创建这些对象了
- 提供了执行sql语句的能力,不用你执行sql
- 提供了循环sql,把sql的结果转为java对象,List集合的能力
while (rs.next()) {
Student stu = new Student();
stu.setId(rs.getInt(“id”));
stu.setName(rs.getString(“name”));
stu.setAge(rs.getInt(“age”));
//从数据库取出数据转为 Student 对象,封装到 List 集合
stuList.add(stu);
} - 提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet
开发人员做的是: 提供sql语句
开发人员提供sql语句————mybatis处理sql————开发人员得到List集合或java对象(表中的数据)
总结:
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行。
回顾JDBC
public void findStudent() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//注册 mysql 驱动
Class.forName("com.mysql.jdbc.Driver");
//连接数据的基本信息 url ,username,password
String url = "jdbc:mysql://localhost:3306/springdb";
String username = "root";
String password = "123456";
//创建连接对象
conn = DriverManager.getConnection(url, username, password);
//保存查询结果
List<Student> stuList = new ArrayList<>();
//创建 Statement, 用来执行 sql 语句
stmt = conn.createStatement();
//执行查询,创建记录集,
rs = stmt.executeQuery("select * from student");
while (rs.next()) {
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
//从数据库取出数据转为 Student 对象,封装到 List 集合
stuList.add(stu);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//关闭资源
if (rs != null)
{
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用JDBC的缺陷
-
代码比较多,开发效率低
-
需要关注 Connection ,Statement, ResultSet 对象创建和销毁
-
对 ResultSet 查询的结果,需要自己封装为 List
-
重复的代码比较多些
-
业务代码和数据库的操作混在一起
快速开始:IDEA方式创建第一个MyBatis项目
实现步骤 ∶
1.新建的student表
2.新建web maven工程、加入maven的mybatis坐标、mysal驱动的坐标
3.创建实体类,Student类--保存表中的一行数据的
4.创建持久层的dao接口,定义操作数据库的方法
5.创建一个mybatis使用的配置文件——sql映射xml文件∶ 写sql语句的。一般一个表一个sql映射文件
5.1 在接口所在IDE目录中
5.2 文件名称和接口保持一致
注意:需要加上maven的资源拷贝插件(Maven在打包的时候默认只将src/main/resource里的配置文件(非.java文件)打包编译到 target/classes里。)
6.创建mybatis的主配置文件∶一个项目就一个主配置文件。主配置文件提供了数据库的连接信息和sql映射文件的位置信息
7.测试。创建使用mybatis类,通过mybatis访问数据库
案例:
1.新建的student表
CREATE TABLE `student` (
`id` int(11) NOT NULL ,
`name` varchar(16) DEFAULT NULL,
`email` varchar(16) DEFAULT NULL,
`age` int(3) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.新建web maven工程

加入maven的mybatis坐标、mysal驱动的坐标 、maven的资源拷贝插件
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
</dependencies>
<build>
<!-- 资源拷贝插件 -->
<resources>
<!-- 把 resource下 的配置文件打包到classes-->
<resource>
<directory>src/main/resources</directory>
</resource>
<!-- 把 非resource下 的配置文件打包到classes-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
3.创建实体类,Student类–保存表中的一行数据的
public class Student {
//定义属性, 目前要求是属性名和列名一样。
private Integer id;
private String name;
private String email;
private Integer age;
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
4.创建持久层的dao接口,定义操作数据库的方法
public interface StudentDao {
//查询student表的所有的数据
public List<Student> selectStudents();
}
5.创建一个sql映射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="study.dao.StudentDao">
<select id="selectStudents" resultType="study.domain.Student" >
select id,name,email,age from student order by id
</select>
</mapper>
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="study.dao.StudentDao">
<!--
select:表示查询操作。
id: 你要执行的sql语法的唯一标识, mybatis会使用这个id的值来找到要执行的sql语句
可以自定义,但是要求你使用接口中的方法名称。
resultType:表示结果类型的, 是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
值写的类型的全限定名称
-->
<select id="selectStudents" resultType="study.domain.Student" >
select id,name,email,age from student order by id
</select>
</mapper>
<!--
sql映射文件(sql mapper): 写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的。
2.约束文件作用: 限制,检查在当前文件中出现的标签,属性必须符合mybatis的要求。
3.mapper 是当前文件的根标签,必须的。
namespace:叫做命名空间,唯一值的, 可以是自定义的字符串。
要求你使用dao接口的全限定名称。
4.在当前文件中,可以使用特定的标签,表示数据库的特定操作。
<select>:表示执行查询,select语句
<update>:表示更新数据库的操作, 就是在<update>标签中 写的是update sql语句
<insert>:表示插入, 放的是insert语句
<delete>:表示删除, 执行的delete语句
-->
6.创建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>
<environments default="mydev">
<environment id="mydev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="study/dao/StudentDao.xml"/>
</mappers>
</configuration>
配置文件解析:
<?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值一样。
告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库
-->
<environments default="mydev">
<!-- environment : 一个数据库信息的配置, 环境
id:一个唯一值,自定义,表示环境的名称。
-->
<environment id="mydev">
<!--
transactionManager :mybatis的事务类型
type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,连接数据库的
type:表示数据源的类型, POOLED表示使用连接池
-->
<dataSource type="POOLED">
<!--
driver, user, username, password 是固定的,不能自定义。
-->
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<!--支持中文的 url:-->
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
<!--一个mapper标签指定一个文件的位置。
从类路径开始的路径信息。 target/clasess(类路径) 编译后有个target文件夹,下面的clasess目录
-->
<mapper resource="study/dao/StudentDao.xml"/>
</mappers>
</configuration>
<!--
mybatis的主配置文件: 主要定义了数据库的配置信息, sql映射文件的位置
1. 约束文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
mybatis-3-config.dtd:约束文件的名称
2. configuration 根标签。
-->
7.测试。创建使用mybatis类,通过mybatis访问数据库
public class MyApp {
public static void main(String[] args) throws IOException {
//访问mybatis读取student数据
//1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
String config="mybatis.xml";
//2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建了SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
//String sqlId = "study.dao.StudentDao" + "." + "selectStudents";
String sqlId = "study.dao.StudentDao.selectStudents";
//7. 重要】执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
//8.输出结果
//studentList.forEach( stu -> System.out.println(stu));
for(Student stu : studentList){
System.out.println("查询的学生="+stu);
}
//9.关闭SqlSession对象
sqlSession.close();
}
}
运行,控制台输出:
查询的学生=Student{id=1001, name='张三', email='zhangsan@qq.com', age=1}
查询的学生=Student{id=1002, name='李四', email='lisi@qq.com', age=2}
开启日志功能
mybatis.xml 文件加入日志配置,可以在控制台输出执行的 sql 语句和参数
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
运行上面的MyApp类main方法
控制台打印:

基本的CURD
自定义 创建sqlSession 工具类
把重复的代码提取出来,创建成工具类
package study.utils;
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
//1.mybatis主配置文件
String config="mybatis.xml";
try {
//2.读取mybatis主配置文件
InputStream in = Resources.getResourceAsStream(config);
//3.4.创建SqlSessionFactory对象,使用SqlSessionFactoryBuilder
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession的方法
public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
if( factory != null){
//5.获取SqlSession对象,从SqlSessionFactory中获取 非自动提交事务 的SqlSession
sqlSession = factory.openSession();
}
return sqlSession;
}
}
insert
StudentDao 接口中增加方法
//插入方法
//参数: student ,表示要插入到数据库的数据
//返回值: int , 表示执行insert操作后的 影响数据库的行数
public int insertStudent(Student student);
StudentDao.xml 加入 sql 语句
<!--插入操作-->
<insert id="insertStudent">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
增加单元测试方法
pom.xml加入junit4依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
package study;
public class TestMyBatis {
@Test
public void testInsert() throws IOException {
//重复代码都在MyBatisUtils.getSqlSession(), 创建 没有自动提交功能 的 SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession(false);
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqlId = "study.dao.StudentDao.insertStudent";
//7. 重要】执行sql语句,通过sqlId找到语句
Student student = new Student();
student.setId(1006);
student.setName("关羽");
student.setEmail("guanyu@163.com");
student.setAge(20);
int nums = sqlSession.insert(sqlId,student);
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
sqlSession.commit();
//8.输出结果
System.out.println("执行insert的结果="+nums);
//9.关闭SqlSession对象
sqlSession.close();
}
}
update
StudentDao 接口中增加方法
//返回值: int , 表示执行update操作后的 影响数据库的行数
int updateStudent(Student student);
StudentDao.xml 加入 sql 语句
<update id="updateStudent">
update student set age = #{age} where id=#{id}
</update>
增加单元测试方法
@Test
public void testUpdate() throws IOException {
//重复代码都在MyBatisUtils.getSqlSession(),创建 有自动提交功能的SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession(true);
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqlId = "study.dao.StudentDao.updateStudent";
//7. 重要】执行sql语句,通过sqlId找到语句
Student student = new Student();
student.setId(1006);
student.setAge(10);
int nums = sqlSession.update(sqlId,student);
//不需要再写sqlSession.commit();
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
//sqlSession.commit();
//8.输出结果
System.out.println("执行insert的结果="+nums);
//9.关闭SqlSession对象
sqlSession.close();
}
delete
StudentDao 接口中增加方法
//返回值: int , 表示执行delete操作后的 影响数据库的行数
int deleteStudent(int id);
StudentDao.xml 加入 sql 语句
<delete id="deleteStudent">
delete from student where id = #{id}
</delete>
增加单元测试方法
@Test
public void testDelete() throws IOException {
//重复代码都在MyBatisUtils.getSqlSession(),创建 有自动提交功能的SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession(true);
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqlId = "study.dao.StudentDao.deleteStudent";
//7. 重要】执行sql语句,通过sqlId找到语句
Student student = new Student();
student.setId(1006);
int nums = sqlSession.delete(sqlId,student);
//不需要再写sqlSession.commit();
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
//sqlSession.commit();
//8.输出结果
System.out.println("执行insert的结果="+nums);
//9.关闭SqlSession对象
sqlSession.close();
}
Idea的代码模板
下次写dao映射文件就有模板了

设置好模板,下次新建就有 mybatis-mapper 可以选择

MyBatis 对象分析
Resources 类
Resources 类,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象。
//读取主配置文件
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactoryBuilder 类
用于创建SqlSessionFactory对象。
SqlSessionFactory 的创建,需要使用 SqlSessionFactoryBuilder 对象的 build() 方法。由 于SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁。所以,一般会将该 SqlSessionFactoryBuilder 对象创建为一个方法内的局部对象,方法结束,对象销毁。
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
SqlSessionFactory 接口
SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用只需要一个该对象即可。接口实现类:DefaultSqlSessionFactory。
SqlSessionFactory作用:获取SqlSession对象。
SqlSession sqlSession = factory.openSession();
SqlSessionFactory.openSession()方法:
openSession(true):创建一个 有自动提交功能 的 SqlSession
openSession(false):创建一个 没有自动提交功能 的 SqlSession,需手动提交
openSession(): 同 openSession(false)
案例:
//省略其他代码...
//5.获取SqlSession对象,从SqlSessionFactory中获取一个 有自动提交功能 的 SqlSession
SqlSession sqlSession = factory.openSession(true);
//省略其他代码...
//不需要再写sqlSession.commit();
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
// sqlSession.commit();
//省略其他代码...
SqlSession 接口
SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()等方法。
SqlSession接口的实现类DefaultSqlSession。
SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。
使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。在执行完sql语句后,需要关闭它,执行SqlSession.close()。 再次需要会话,再次创建。这样能保证他的使用是线程安全的。
mybatis动态代理
上面的例子都没有使用动态代理的方式。
mybatis动态代理:不用创建实现类,直接调用 SqlSession.getMapper(dao接口.class),就可以得到dao接口的实现类。
使用动态代理方式步骤:
1.获取SqlSession对象,SqlSessionFactory.openSession()
2.使用getMapper方法获取某个接口的对象,sqlSession.getMapper(接口.class)
3.调用dao接口的方法,就执行了mapper文件中的sql语句
使用动态代理的要求:
1.dao接口和mapper文件放在一起,同一个目录
2.dao接口和mapper文件名称一致
3.mapper文件中的namespace的值是dao接口的全限定名称
4.mapper文件中的<select>,<insert>,<update>,<delete>等的id是接口中方法名称
5.dao接口中不要使用重载方法,不要使用同名的,不同参数的方法
下面的案例使用了动态代理:
StudentDao 接口
public interface StudentDao {
List<Student> selectStudents();
}
StudentDao.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="study.dao.StudentDao">
<select id="selectStudents" resultType="study.domain.Student">
select id,name,email,age from student order by id
</select>
</mapper>
测试
@Test
public void testSelectStudents(){
SqlSession sqlSession = MyBatisUtils.getSqlSession(false);
//使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口)能获取dao接口对应的实现类对象
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
//com.sun.proxy.$Proxy2 : jdk的动态代理
System.out.println(studentDao.getClass().getName());
//调用dao的方法, 执行数据库的操作
List<Student> students = studentDao.selectStudents();
for(Student stu: students){
System.out.println("学生="+stu);
}
}
参数
parameterType
parameterType: 接口中方法参数的类型, 类型的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从 java 代码传入到mapper 文件的 sql 语句。
例如:
<delete id="deleteStudent" parameterType="int">
delete from student where id=#{studentId}
</delete>
等同于
<delete id="deleteStudent" parameterType="java.lang.Integer">
delete from student where id=#{studentId}
</delete>
可以针对parameterType或resultType指定的类型定义、使用一些别名。
mybatis默认支持的别名:
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
使用_int等时,idea可能会报红,是idea的问题,不影响程序。
MyBatis 传递参数
从 java 代码中把参数传递到 mapper.xml 文件的sql语句中。
一个简单类型的参数
在mapper文件获取简单类型的一个参数的值,使用EL表达式: #{任意字符} 。
简单类型: mybatis把java的基本数据类型和String都叫简单类型。
例如:
接口方法:
Student selectById(int id);
mapper 文件:
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
#{studentId} , studentId 是自定义的变量名称,和方法参数名无关。
简单理解#{}的原理:
使用#{}之后, mybatis执行sql是使用的jdbc中的PreparedStatement对象
由mybatis执行下面的代码:
1. mybatis创建Connection , PreparedStatement对象
String sql="select id,name, email,age from student where id=?";
PreparedStatement pst = conn.preparedStatement(sql);
pst.setInt(1,1001);
2. 执行sql封装为resultType="Student"这个对象
ResultSet rs = ps.executeQuery();
Student student = null;
while(rs.next()){
//从数据库取表的一行数据, 存到一个java对象属性中
student = new Student();
student.setId(rs.getInt("id));
student.setName(rs.getString("name"));
student.setEmail(rs.getString("email"));
student.setAge(rs.getInt("age"));
}
return student; //给了dao方法调用的返回值
多个参数使用 @Param命名参数
当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”),mapper 文件使用#{自定义参数名}。
例如:
接口:
public List<Student> selectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
mapper文件:
<select id="selectMultiParam" resultType="study.domain.Student">
select id,name, email,age from student where name = #{myname} or age = #{myage}
</select>
多个参数 使用对象
使用 java 对象传递参数, java对象 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。
语法格式: #{ property,javaType=java 中数据类型名,jdbcType=数据类型名称 }
。
javaType:指java中的属性数据类型。
jdbcType:在数据库中的数据类型。
例如:
#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
常用格式:#{ property }
。javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。
案例:
创建一个对象
public class QueryParam {
private String paramName;
private Integer paramAge;
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public Integer getParamAge() {
return paramAge;
}
public void setParamAge(Integer paramAge) {
this.paramAge = paramAge;
}
}
StudentDao 接口中增加方法
/**
* 多个参数,使用java对象作为接口中方法的参数
*/
List<Student> selectMultiObject(QueryParam param);
StudentDao.xml 加入 sql 语句
<select id="selectMultiObject" resultType="study.domain.Student">
select id, name, email, age
from student
where name = #{paramName}
or age = #{paramAge}
</select>
增加单元测试方法
@Test
public void testSelectMultiObject(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
QueryParam queryParam = new QueryParam();
queryParam.setParamName("张三");
queryParam.setParamAge(28);
List<Student> students = studentDao.selectMultiObject(queryParam);
for(Student stu: students){
System.out.println("学生="+stu);
}
sqlSession.close();
}
多个参数按位置
参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0}
, 第二个是#{arg1}
。
注意:mybatis-3.3 版本和之前的版本使用#{0},#{1}方式, 从 mybatis3.4 开始使用#{arg0}方式。
案例:
StudentDao 接口中增加方法
/**
* 多个参数-简单类型的,按位置传值,
* mybatis 3.4之前,使用 #{0},#{1}
* mybatis 3.4之后,使用 #{arg0},#{arg1}
*/
List<Student> selectMultiPosition( String name,Integer age);
StudentDao.xml 加入 sql 语句
<select id="selectMultiPosition" resultType="study.domain.Student">
select id, name, email, age
from student
where name = #{arg0}
or age = #{arg1}
</select>
多个参数使用Map
Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key,Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值。
案例:
StudentDao 接口中增加方法
/**
* 多个参数,使用Map存放多个值
*/
List<Student> selectMultiByMap(Map<String,Object> map);
StudentDao.xml 加入 sql 语句
<!--多个参数,使用Map , 使用语法 #{map的key}-->
<select id="selectMultiByMap" resultType="study.domain.Student">
select id, name, email, age
from student
where name = #{myname}
or age = #{myage1}
</select>
增加单元测试方法
@Test
public void testSelectMultiByMap(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Map<String,Object> map = new HashMap<>();
map.put("myname","张三"); // #{myname}
map.put("myage1",28); //#{myage1}
List<Student> students = studentDao.selectMultiByMap(map);
for(Student stu: students){
System.out.println("学生="+stu);
}
sqlSession.close();
}
“#” 和 “$” 的区别
- #使用 ?在sql语句中做占位的,使用PreparedStatement执行sql,效率高。
- #能够避免sql注入,更安全。
- $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低。
- $有sql注入的风险,缺乏安全性。
- $可以替换表名或者列名。
#:占位符
告诉 mybatis 使用实际的参数值代替。
并使用 PrepareStatement 对象执行 sql 语句,#{…}代替sql 语句的"?"。这样做更安全,更迅速,通常也是首选做法。
例如有如下sql映射,在测试方法传入id=1001
<select id="selectById" resultType="study.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
#的结果: select id,name, email,age from student where id=?
转为 MyBatis 的执行是:
String sql="select id,name,email,age from student where id=?"; //就是 where id=#{studentId}
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005); //1005 会替换掉 #{studentId}
$: 字符串替换
告诉 mybatis 使用${…}包含的“字符串”替换所在位置。
并使用 Statement 把 sql 语句和${…}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。
例如有如下sql映射,在测试方法传入id=1001
<select id="findById" resultType="study.domain.Student">
select * from student where id = #{studentId}
</select>
$的结果:select id,name, email,age from student where id=1001
转为 MyBatis 的执行是:
String sql="select id,name, email,age from student where id=" + "1001";
$:可以替换表名或者列名,能确定数据是安全的。可以使用
案例:
StudentDao 接口中增加方法
List<Student> selectUse$Order(@Param("col") String colName);
StudentDao.xml 加入 sql 语句
<!--$替换列名-->
<select id="selectUse$Order" resultType="study.domain.Student">
select * from student order by ${col}
</select>
测试方法
@Test
public void testSelectUse$Order(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectUse$Order("age");
// List<Student> students = dao.selectUse$Order("name");
// List<Student> students = dao.selectUse$Order("id");
for(Student stu: students){
System.out.println("学生="+stu);
}
sqlSession.close();
}
}
封装 MyBatis 输出结果
mybatis执行了sql语句,得到java对象。
resultType
resultType: 执行 sql 得到 ResultSet 转换的类型,类型是任意的,使用类型的完全限定名或别名,例如 java.lang.Integer别名是int。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。
处理方式:
1、mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。
2、mybatis把ResultSet指定的列的值 付值给 对象的同名的属性(调用列名对应的 setxxx 方法)。
简单类型
案例:
接口方法
int countStudent();
mapper映射文件
<!--使用类型的完全限定名或别名-->
<!--<select id="countStudent" resultType="int">-->
<select id="countStudent" resultType="java.lang.Integer">
select count(*) from student
</select>
对象类型
案例:
<!--执行完sql语句,要转化为Student对象-->
<select id="selectMultiPosition" resultType="study.domain.Student">
<!--要执行的sql语句-->
select id,name, email,age from student
</select>
//对等的jdbc
ResultSet rs = executeQuery(" select id,name, email,age from student" )
while(rs.next()){
Student student = new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"))
}
Map
sql 的查询结果作为 Map 的 key 和 value。推荐使用 Map<Object,Object>。列名是map的key,列值是map的value。
注意:Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录是错误的。要返回多个Map,要用List封装Map。
案例:
接口方法
//定义方法返回Map
Map<Object,Object> selectMapById(Integer id);
<select id="selectMapById" resultType="java.util.HashMap">
select id,name,email from student where id = #{stuid}
</select>
@Test
public void testSelecMap(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Map<Object,Object> map = dao.selectMapById(1001);
System.out.println("map=="+map);
}
控制台打印:
map=={name=张三, id=1001, email=zhangsan@qq.com}
定义自定义类型的别名
在mybatis主配置文件中定义,使用<typeAlias>
的方式 或者 <package>
的方式。
可以在resultType中使用自定义别名
<typeAlias>
在mybatis主配置文件中定义
<!--定义别名-->
<typeAliases>
<!--
第一种方式:
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<typeAlias type="自定义类型的全限定名称" alias="别名"/>
<typeAlias type="自定义类型的全限定名称" alias="别名"/>
</typeAliases>
案例:
mybatis主配置文件:
<typeAliases>
<typeAlias type="study.domain.Student" alias="stu"/>
<typeAlias type="study.vo.ViewStudent" alias="vstu"/>
</typeAliases>
接口方法
public Student selectStudentById(@Param("studentId") Integer id);
mapper映射文件
<select id="selectStudentById" resultType="stu">
select id,name, email,age from student where id=#{studentId}
</select>
<package>
在mybatis主配置文件中定义
<!--定义别名-->
<typeAliases>
<!--
第二种方式
<package> name是包名,这个包中的所有类,类名就是别名(类名不区分大小写)
-->
<package name="包名"/>
<package name="包名"/>
</typeAliases>
案例:
mybatis主配置文件:
<typeAliases>
<package name="study.domain"/>
<package name="study.vo"/>
</typeAliases>
接口方法
ViewStudent selectStudentReturnViewStudent(@Param("sid") Integer id);
mapper映射文件
<!--类名就是别名(类名不区分大小写)-->
<select id="selectStudentReturnViewStudent" resultType="viewStudent">
select id,name from student where id=#{sid}
</select>
resultMap
resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和 java 对象属性名不一样的情况。
使用方式:
1.先定义 resultMap,指定列名和属性的对应关系。
2.在中把 resultType 替换为 resultMap。(不能一起使用)
<!--
定义resultMap
id:自定义名称,表示你自定义的这个resultMap
type:java类的全限定名称
-->
<resultMap id="studentMap" type="study.domain.Student">
<!--列名和java属性的关系-->
<!--主键列,使用id标签-->
<!--
column :数据库表列名
property:java类的属性名
-->
<id column="id" property="id" />
<!--非主键列,使用result标签-->
<result column="数据库表列名" property="类的属性名" />
<result column="数据库表列名" property="类的属性名" />
<result column="数据库表列名" property="类的属性名" />
</resultMap>
<select id="方法名" resultMap="studentMap">
select语句
</select>
案例:
接口方法
List<Student> selectAllStudents();
mapper映射文件
<resultMap id="studentMap" type="study.domain.Student">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
select id,name, email,age from student
</select>
实体类属性名和数据库表列名不同时的处理方式
案例:
例如有新的实体类MyStudent类
public class MyStudent {
private Integer stuid;
private String stuname;
private String stuemail;
private Integer stuage;
//省略setter、getter、toString方法
数据库表的列名是id、name、email、age。此时实体类的属性名和数据库表的列名是对应不上的。
解决方式1:使用resultMap
接口方法
List<MyStudent> selectDiffColProperty();
mapper映射文件
<!--列名和属性名不一样:第一种方式-->
<resultMap id="myStudentMap" type="study.domain.MyStudent">
<id column="id" property="stuid" />
<result column="name" property="stuname" />
<result column="email" property="stuemail" />
<result column="age" property="stuage" />
</resultMap>
<select id="selectDiffColProperty" resultMap="myStudentMap">
select id,name, email , age from student
</select>
解决方式2:使用列别名 + resultType
接口方法
List<MyStudent> selectDiffColProperty();
mapper映射文件
<!--
列名和属性名不一样:第二种方式
resultType的默认原则是:同名的列值 赋值给 同名的属性,使用列别名(java对象的属性名)
id as stuid 给数据表列加上别名,那么 列名 就能与 对象属性名 对应上了
-->
<select id="selectDiffColProperty" resultType="study.domain.MyStudent">
select id as stuid, name as stuname, email as stuemail, age as stuage
from student
</select>
Like模糊查询
模糊查询的实现有两种方式: 一是 java 代码中给查询数据加上"%" ; 二是在 mapper 文件 sql 语句的条件位置加上"%" 。推荐使用更灵活的第一种方式。
1、第一种模糊查询, 在java代码指定 like的内容。使用#{…}。
案例:
接口方法
List<Student> selectLikeOne(String name);
mapper映射文件
<!--第一种 like , java代码指定 like的内容-->
<select id="selectLikeOne" resultType="study.domain.Student">
select id, name, email, age
from student
<!--注意这里使用的是 # 。 使用$会报错-->
where name like #{name}
</select>
测试
@Test
public void testSelectLike(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//准备好like的内容
String name = "%张%";
List<Student> students = dao.selectLikeOne(name);
for(Student stu: students){
System.out.println("#######学生="+stu);
}
sqlSession.close();
}
2、第二种模糊查询,在mapper文件sql语句条件中拼接,使用 like name “%” #{xxx} “%”。
案例:
接口方法
List<Student> selectLikeOne(String name);
mapper映射文件
<!--第二种方式:在mapper文件中拼接 like的内容-->
<select id="selectLikeOne" resultType="study.domain.Student">
select id, name, email, age
from student
<!--注意这里使用的是 # 。 使用$会报错-->
where name like "%" #{name} "%"
</select>
测试
@Test
public void testSelectLike(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//准备好like的内容
String name = "张";
List<Student> students = dao.selectLikeOne(name);
for(Student stu: students){
System.out.println("*******学生="+stu);
}
sqlSession.close();
}
动态sql
sql的内容是变化的(主要是where部分发生变化),可以根据条件获取到不同的sql语句。
动态 SQL,通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句。这里的条件判断使用的表达式为 OGNL 表达式。常用的动态 SQL 标签有、、、等。
动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题。
在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。
特别是对于小于号(<),在 XML 中是绝不能出现的。否则解析 mapper 文件会出错。
实体符号表:
实体符号 | ||
---|---|---|
< | 小于 | < |
> | 大于 | > |
<= | 小于等于 | <= |
>= | 大于等于 | >= |
<if>标签
对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。
语法:
<if test="条件">
sql语句的部分
</if>
案例:
接口方法
List<Student> selectStudentIf(Student student);
mapper映射文件
<!-- <if:test="使用参数java对象的属性值作为判断条件>-->
<select id="selectStudentIf" resultType="study.domain.Student">
select id,name, age, email
from student
where 1=1
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
测试
@Test
public void testSelectStudentIf(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setName("李四");
student.setAge(20);
List<Student> students = dao.selectStudentIf(student);
for(Student stu:students){
System.out.println("if==="+stu);
}
}
分析:
mapper映射文件里
where 1=1
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
为什么 sql语句的部分 要加上 and、or?为什么要 where 1=1 ?
控制台打印的sql语句:
select id,name, age, email from student where 1=1 and name = ? or age > ?
加上and、or、1=1都是为了语句的拼接。
不加上会报sql语法错误。比如说去掉1=1,当name和age的条件都满足时,sql语句变为select id,name, age, email from student where and name = ? or age > ?。...where and... 这明显是有sql语法错误的。
<where>标签
使用标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加where 子句。
需要注意的是,第一个标签中的 SQL 片断,可以不包含 and、or等。不过,写上 and 也不错,mybatis会将多余的 and、or等去掉。但其它中 SQL 片断的 and、or等,必须要求写上。否则 SQL 语句将拼接出错。
语法:
<where>
其他动态 sql
</where>
案例:
接口方法
List<Student> selectStudentWhere(Student student);
mapper映射文件
<select id="selectStudentWhere" resultType="study.domain.Student">
select id,name, age, email
from student
<where>
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
分析:
mapper映射文件里
<where>
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
当两个条件都满足时,控制台打印语句:
select id,name, age, email from student WHERE name = ? or age > ?
发现会把and name = #{name}前面的and去掉了(mybatis会将多余的 and、or等去掉)。
<foreach>标签
标签用于实现对于数组与集合的遍历。
语法:
<foreach collection="集合类型" item="集合中的成员" open="开始的字符" close="结束的字符" separator="集合成员之间的分隔符">
#{item 的值}
</foreach>
collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
item:自定义的,表示数组和集合成员的变量
open:循环开始是的字符
close:循环结束时的字符
separator:集合成员之间的分隔符
遍历 List<简单类型>
案例:
需求:查询学生 id 是 1002,1005,1006
接口方法
List<Student> selectForeach(List<Integer> idlist);
mapper映射文件
<select id="selectForeach" resultType="study.domain.Student">
select * from student
<!--表达式中的 List 使用 list 表示,其大小使用 list.size 表示-->
<if test="list !=null and list.size > 0 ">
where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</if>
</select>
测试
@Test
public void testSelectForEach(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Integer> list = new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);
List<Student> students = studentDao.selectForeach(list);
for(Student stu:students){
System.out.println("foreach--one ==="+stu);
}
}
遍历 List<对象类型>
案例:
接口方法
List<Student> selectForeach(List<Student> stulist);
mapper映射文件
<select id="selectForeach" resultType="study.domain.Student">
select * from student
<!--表达式中的 List 使用 list 表示,其大小使用 list.size 表示-->
<if test="list != null and list.size > 0 ">
where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</if>
</select>
其他写法:
<select id="selectForeach" resultType="study.domain.Student">
<!--<include refid="studentSql"/>-->
select * from student
where id in (
<foreach collection="list" item="stu">
#{stu.id},
</foreach>
-1 )
</select>
测试
@Test
public void testSelectForTwo(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> stuList = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
stuList.add(s1);
s1 = new Student();
s1.setId(1001);;
stuList.add(s1);
List<Student> students = dao.selectForeach(stuList);
for(Student stu:students){
System.out.println("foreach--two ==="+stu);
}
}
代码片段
标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用子标签。该标签可以定义 SQL 语句中的任何部分,所以子标签可以放在动态 SQL的任何位置。
案例:
<!--定义sql片段-->
<sql id="studentSql">
select id, name, age, email
from student
</sql>
<select id="selectStudentIf" resultType="study.domain.Student">
<!--引入sql片段-->
<include refid="studentSql"/>
where 1=1
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
<!--定义sql片段-->
<sql id="studentSqlOne">
id,name, age, email
</sql>
<select id="selectStudentWhere" resultType="study.domain.Student">
select
<!--引入sql片段-->
<include refid="studentSqlOne"/>
from student
<where>
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
MyBatis 主配置文件
上面案例中 mybatis.xml 是主配置文件。
特点
1、需要在头部使用约束文件:
<?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">
2、根元素 ,其他元素都需要在根元素里面配置。
在填写标签的时候一定要注意相关配置的顺序。
properties
创建jdbc.properties文件,存放数据库配置信息。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.user=root
jdbc.passwd=123456
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>
<!--指定jdbc.properties文件的位置,从类路径根开始找文件-->
<!--
引入外部配置文件,类似于Spring中的property-placeholder
resource:从类路径引入
url:从磁盘路径或者网络路径引入
-->
<properties resource="db.properties"></properties>
<environments default="mydev">
<environment id="mydev">
<!--
transactionManager:mybatis提交事务,回滚事务的方式
type: 事务的处理的类型
1)JDBC : 表示mybatis底层是调用JDBC中的Connection对象的,commit, rollback
2)MANAGED : 把mybatis的事务处理委托给其它的容器(一个服务器软件,一个框架(spring))
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
数据源表示Connection对象的。
type:指定数据源的类型
1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
3)JNDI:java命名和目录服务(windows注册表)
-->
<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.passwd}"/>
</dataSource>
</environment>
</environments>
</configuration>
settings
用来控制mybatis运行时的行为,是mybatis中的重要配置。
比如上面案例都使用的:
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
其他配置:
<!--settings:控制mybatis全局行为-->
<!-- settings是 MyBatis 中全局的调整设置,它们会改变 MyBatis 的运行时行为,应谨慎设置 -->
<settings>
<!-- 该配置影响的所有映射器中配置的缓存的全局开关。默认值true -->
<setting name="cacheEnabled" value="true"/>
<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认值false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 是否允许单一语句返回多结果集(需要兼容驱动)。 默认值true -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!-- 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。默认值true -->
<setting name="useColumnLabel" value="true"/>
<!-- 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 默认值false -->
<setting name="useGeneratedKeys" value="false"/>
<!-- 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 -->
<!-- 默认值PARTIAL -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!-- 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。默认SIMPLE -->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 设置超时时间,它决定驱动等待数据库响应的秒数。 -->
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<!-- 允许在嵌套语句中使用分页(RowBounds)默认值False -->
<setting name="safeRowBoundsEnabled" value="false"/>
<!-- 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 默认false -->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。
若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 -->
<setting name="localCacheScope" value="SESSION"/>
<!-- 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 -->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!-- 指定哪个对象的方法触发一次延迟加载。 -->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
mappers
指定sql mapper(sql映射文件)的位置。
(1)
使用相对于类路径的资源,从 classpath 路径查找文件
例如:
<mappers>
<!--第一种方式:指定多个mapper文件-->
<mapper resource="study/dao/StudentDao.xml"/>
<mapper resource="study/dao/OrderDao.xml" />
</mappers>
(2)
使用包名。
name: xml文件(mapper文件)所在的包名,这个包中所有xml文件一次都能加载给mybatis。
使用package的要求:
- mapper文件名称需要和接口名称一样, 区分大小写的一样。
- mapper文件和dao接口需要在同一目录。
<mappers>
<!--第二种方式: 使用包名-->
<package name="study.dao"/>
</mappers>
rue 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 默认值false -->
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!-- 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。默认SIMPLE -->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 设置超时时间,它决定驱动等待数据库响应的秒数。 -->
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<!-- 允许在嵌套语句中使用分页(RowBounds)默认值False -->
<setting name="safeRowBoundsEnabled" value="false"/>
<!-- 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 默认false -->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。
若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 -->
<setting name="localCacheScope" value="SESSION"/>
<!-- 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 -->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!-- 指定哪个对象的方法触发一次延迟加载。 -->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
## mappers
指定sql mapper(sql映射文件)的位置。
(1)<mapper resource=" " />
使用相对于类路径的资源,从 classpath 路径查找文件
例如:
```xml
<mappers>
<!--第一种方式:指定多个mapper文件-->
<mapper resource="study/dao/StudentDao.xml"/>
<mapper resource="study/dao/OrderDao.xml" />
</mappers>
(2)
使用包名。
name: xml文件(mapper文件)所在的包名,这个包中所有xml文件一次都能加载给mybatis。
使用package的要求:
- mapper文件名称需要和接口名称一样, 区分大小写的一样。
- mapper文件和dao接口需要在同一目录。
<mappers>
<!--第二种方式: 使用包名-->
<package name="study.dao"/>
</mappers>