MyBatis是一个持久层(DAO)框架,本质上是JDBC的一次封装。
MyBatis是一个持久层框架,那么作用当然就是操作数据库(增删改查 CRUD )。
MyBatis的理念:让开发者编写10%的代码(相对于原生JDBC)就可以实现数据库的操作。解决方案:持久层(DAO)的零实现,所谓的零实现,就是不用写实现类代码,直接使用接口就可以操作数据库。
MyBatis 的定义, 提高开发的效率、程序的健壮性、可扩展性、优雅性!!!真的写很少代码就可以增删改查。在同等实现效果下,显著减少技术代码的编写,从而可以让开发人员关注业务逻辑代码的编写。
借用jQuery的理念就是:写的更少,做的更多(write less do more)。
MyBatis框架能够让我们以最少的代码实现操作数据库。从而提高开发的效率!!!
--如何将代码减少呢?
【1】持久层的零实现 (不需要写实现类,底层通过动态代理实现)。
【2】无需编写结果集ResultSet和javaBean属性之间的映射关系的java代码,通过xml
配置文件配置即可。
配置文件的作用记载对象和对象之间的映射关系或者依赖关系,在程序运行过程中动态的读取配置文件中的信息完成特定的程序应用。
Resources:资源类,用于读取总配置文件。
SqlSessionFactoryBuilder:会话工厂构造类,通过读取的总配置文件构建会话工厂。
SqlSessionFactory:会话工厂。
SqlSession:会话操作对象,用于生成对应模块接口的代理对象(0实现)。
MyBatis是一个持久层的框架,所谓的框架,无非就是一群牛逼的人封装了某一个java原生功能,而MyBatis就是对原生JDBC的一次封装,相对于我们自己的封装,MyBatis会更加的强大、健壮、高效,MyBatis的底层实现就是JDBC,我们封装过功能都清楚,封装无非就是将重复一样的代码在一个方法中写死,而那些随着业务场景不同的代码,则通过形参进行控制,封装过后,我们只需将变化的形参传递给封装的方法,那么我们就可以得到既定的返回值,封装把我们从编写繁琐无味的重复性代码中解放出来,从而使得我们可以更加关注业务逻辑代码的编写,进而降低开发成本,提高开发效率。所以学习MyBatis框架,首先学习如何使用Mybatis封装好的方法(功能),清楚MyBatis在开发中的使用流程,在熟练使用MyBatis进行业务开发之后,我们可以尝试的去学习Mybatis的源码,使得我们能更加灵活使用MyBatis进行开发。
MyBatis在项目中的使用流程:
【1】导包(MyBatis和数据库驱动的jar包)。
【2】编写mybatis-config.xml和xxxMapper.xml配置文件。
注意:[1]通常一个项目对应一个数据库实例、而一个数据库实例对应一个mybatis-config.xml配置文件,而项目中的一个模块对应一个xxxMapper.xml配置文件)。
[2] xxxMapper.xml配置文件中编写模块DAO层接口中的抽象方法的sql语句。每一个方法的实际sql类型对应一个标签(select、insert、update、delete),这样做只是为了将代码语义化,方便后期代码维护。
【3】借助MyBatis封装好的SqlSessionFactoryBuilder对象的build方法构建一个数据库实例的
sql会话对象(sqlSession)。
注意:build方法需要一个字节输入流(InputStream),是mybatis-config.xml总配置文件的字节输入流。
【4】通过sql会话对象的getMapper方法构建某一模块DAO层的代理对象(底层实现是动态代理)。
【5】通过代理对象调用模块DAO层接口中定义的方法。
--获得数据库连接
第一步:导入包(任何框架需要的事情)。
第二步:创建总配置文件,文件名可以随便写,官方推荐mybatis-config.xml。
第三步:创建一个MyBatisUtils工具类,(获得SqlSession对象)。
--需求:插入数据到数据库
第四步:创建一个映射接口(如UserMapper)。
第五步:创建一个映射文件(如UserMapper.xml)。
第六步:在总配置文件中配置映射文件(在mybatis-config.xml配置文件中mappers标签中引入一个mapper标签,resources属性值为的映射文件的路径)。
第七步:编写测试插入数据代码(通过UserMapper接口调用UserDao中的方法)。
PS:数据库sql脚本
/* Navicat Premium Data Transfer Source Server : root Source Server Type : MySQL Source Server Version : 50562 Source Host : localhost:3306 Source Schema : users Target Server Type : MySQL Target Server Version : 50562 File Encoding : 65001 Date: 12/12/2019 16:25:24*/ SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0; -- ------------------------------ Table structure for tb_user-- ----------------------------DROP TABLE IF EXISTS `tb_user`;CREATE TABLE `tb_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名', `age` int(11) NULL DEFAULT NULL COMMENT '年龄', `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱', `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 1188715086030696464 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;复制代码
github.com/MyBatis/MyB…
在项目的src(类路径classpath) 下面创建配置文件mybatis-config.xml。
<?xml version="1.0" encoding="UTF-8" ?><!-- dtd约束 --><!DOCTYPE configuration PUBLIC "-//MyBatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><!-- 根元素: 用于配置MyBatis --><configuration> <!-- 配置MyBatis的运行环境 ,可以配置多个环境,但是一次只能使用一个 default属性 : 当前使用的环境 ,使用下面环境的id 即可 --> <environments default="dev_mysql"> <!-- 环境配置 id 属性,唯一标识当前环境 --> <environment id="dev_mysql"> <!-- 配置MyBatis事务管理器 type属性 : 事物类型 JDBC 使用事务(正常提交commit,异常回滚事务 rollback) 默认 MANAGED : 不使用事务 --> <transactionManager type="JDBC"/> <!-- 配置MyBatis的数据源 type : 配置连接池 POOLED :MyBatis内置的一个连接池(默认) 后期都交给spring管理了,配置 dbcp连接池,阿里巴巴的 druid连接池 --> <dataSource type="POOLED"> <!-- 连接数据库的操作 --> <!-- 数据库驱动 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- 连接数据库的url --> <property name="url" value="jdbc:mysql://localhost:3306/users"/> <!-- 连接数据库账号 --> <property name="username" value="root"/> <!-- 连接数据库密码 --> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <!-- <mapper resource="org/cjw/mapper/UserMapper.xml"/>--> <!--指定一个配置文件--> <!--<package name="org.cjw.mapper"/>--> <!-- 指定一个包,包含多个配置文件或者配置类,推荐 --> <mapper class="org.cjw.mapper.UserMapper" /> <!-- 指定一个配置类 --> </mappers></configuration>复制代码MyBatisUtil 2.2.4. 创建MyBatisUtil工具类
工具类的作用主要用于读取配置文件,创建工厂对象,提供创建SqlSession数据库操作对象的方法。
package org.cjw.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 MyBatisUtil { private MyBatisUtil() {} private static SqlSessionFactory sqlSessionFactory; static { try(InputStream in = Resources.getResourceAsStream("mybatis-config.xml")) { sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession openSession() { return sqlSessionFactory.openSession(); }}复制代码
package org.cjw.pojo;public class User { private Long id; private String name; private Integer age; private String email; private String password; public User() { } public User(Long id, String name, Integer age, String email, String password) { this.id = id; this.name = name; this.age = age; this.email = email; this.password = password; } public Long getId() { return id; } public void setId(Long 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 getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}复制代码
package org.cjw.mapper;import org.cjw.pojo.User;public interface UserMapper { /* 使用MyBatis的动态代理开发编写代码遵循四个原则 1.映射文件的namespace命名空间的值必须是对应接口的全限定名。 2.映射文件的对应功能 id值必须等于映射接口中方法的名称。 3.映射文件的参数类型必须和接口中方法的参数类型一致。 4.映射文件查询的返回结果类型必须和接口的方法的返回数据类型一致, DML操作返回的受影响的行数,除外。 */ void insert(User user);}复制代码
<?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="org.cjw.mapper.UserMapper"> <!-- 新增操作 id: 当前功能的唯一标识,和接口方法同名 parameterType : 参数的类型 useGeneratedKeys:是否返回数据库生成的主键 true是/false否 keyProperty : 数据库主键对应java的pojo对象的属性 keyColumn : 数据表的主键列名 --> <insert id="insert" parameterType="org.cjw.pojo.User" keyProperty="id" keyColumn="id"> insert into tb_user (name, age, email, password) values (#{name}, #{age}, #{email}, #{password}); </insert></mapper>复制代码2.2.8. 创建测试类准备测试
@Testpublic void testInsert() { SqlSession session = MyBatisUtil.openSession(); try { UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setName("李四"); user.setAge(14); user.setEmail("lisi@qq.com"); user.setPassword("lisi"); userMapper.insert(user); session.commit(); } catch (Exception e) { e.printStackTrace(); session.rollback(); } finally { session.close(); }}复制代码
log4j是一个日志输出框架,就是用于输出日志的。MyBatis的日志输出是通过log4J输出的。主流框架大部分都是log4j输出的。Spring框架也可以通过log4j输出日志!!
问题:既然log4j功能类似System.out.println(),为什么使用log4j而不直接使用System.out.println()?
答:log4j提供了强大的日志输出的自定义功能。
1.通过级别输出日志(调试、信息、警告、错误、致命异常)。
2.可以指定输出到控制台,以及输出到文件。
3.可以设置输出的日志格式。
所以学习LOG4J.需要学会自定义配置LOG4J的输出格式以及输出等级。
Log4j的下载地址
注意:文件名必须为 log4j.properties
# Global logging configurationlog4j.rootLogger=debug, stdoutlog4j.logger.org.cjw.mapper=TRACE // 需要修改为自己的包名# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n复制代码
<select id="selectUserById" resultType="org.cjw.pojo.User"> select * from tb_user where id = #{id}</select>复制代码
@Testpublic void testSelectUserById() { SqlSession session = MyBatisUtil.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); User user = userMapper.selectUserById(1); System.out.println(user.getName());}复制代码
<!-- 多行查询 resultType : 无论是多行查询还是单行查询,返回的结果类型都是对应的JavaBean的类型--><select id="selectAll" resultType="org.cjw.pojo.User"> select * from tb_user</select>复制代码
@Testpublic void testSelectAll() { SqlSession session = MyBatisUtil.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); List<User> users = userMapper.selectAll(); for (User user : users) { System.out.println(user.getName()); }}复制代码
<delete id="deleteUserById"> delete from tb_user where id = #{id}</delete>复制代码
@Testpublic void testDeleteUserById() { SqlSession session = MyBatisUtil.openSession(); try { UserMapper userMapper = session.getMapper(UserMapper.class); userMapper.deleteUserById(1); session.commit(); } catch (Exception e) { e.printStackTrace(); session.rollback(); } finally { session.close(); }}复制代码
<update id="updateUserById" parameterType="org.cjw.pojo.User"> update tb_user set name = #{name}, age = #{age}, email = #{email}, password = #{password} where id = #{id}</update>复制代码
@Testpublic void testUpdateUserById() { SqlSession session = MyBatisUtil.openSession(); try { UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setId(2L); user.setName("zhangsan"); user.setEmail("zhangsan@126.com"); user.setPassword("zhangsan123123123"); userMapper.updateUserById(user); session.commit(); } catch (Exception e) { e.printStackTrace(); session.rollback(); } finally { session.close(); }}复制代码
MyBatis的查询结果集都是自动映射封装的,单行查询将数据库一条数据封装成对应的Java对象。多行查询,先将每一行封装成对象,再将每个对象添加到集合中,最后返回一个List集合对象。但是:必须保证查询结果集和pojo对象的属性名相同,否则无法自动封装。
问题:如何解决查询结果集名称和pojo对象属性不同的映射封装?
解决方案:1.使用手动映射封装 <resultMap> 标签。2.可以使用MyBatis的驼峰命名法,但是也必须遵循一定规则才行。
<select id="selectUserById" resultMap="user_map"> select id u_id, name u_name, age u_age, email u_email, password u_password from tb_user where id = #{id}</select><resultMap id="user_map" type="User"> <id property="id" column="u_id" /> <result property="name" column="u_name"/> <result property="age" column="u_age"/> <result property="email" column="u_email"/> <result property="password" column="u_password"/></resultMap>复制代码
<environments>:环境集标签,就是用于配置数据库的连接信息的。
<environment>:用于配置具体环境参数。
<transactionManager>:配置使用的事务类型,JDBC。
<dataSource>:配置数据源的参数,POOLED。
具体参数参看PooledDataSource的set方法。
<property>:配置属性
<mappers>: 配置映射文件信息的
<mapper class|resource>: 配置具体指定的mapper文件
class: 配置使用注解时指定有注解的映射接口
resource: 指定映射文件
<package name>: 配置配置文件、配置类所在的包,推荐
<properties>:MyBatis读取classpath路径下配置文件,一般用于读取db.properties。
<typeAliases>:用于配置别名。
<typeAliase type alias>
type:指定取别名的全限定名
alias:别名
<package name>
name:指定取别名的包
<typeHandlers>:用于配置自定义类型处理器。
<settings>:配置MyBatis的默认设置的(开启二级缓存、驼峰命名自动映射)。
总配置文件的标签顺序
<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>
这句话的意思就是configuration标签下的标签的顺序以及标签出现的个数的声明。
根据这个声明可以看到顺序为:
1. properties
2.settings
3.typeAliases
4.typeHandlers
5.objectFactory
6.objectWrapperFactory
7.reflectorFactory
8.plugins
9. environments
10.databaseIdProvider
11.mappers
DTD
规则文件标签的出现的次数说明
如果声明的标签后?: 表示出现0-1次
如果声明的标签后*: 表示出现0-N次
如果声明的标签后+: 表示出现1-N次
如果声明的标签后什么都没有: 表示出现1次
在UserMapper.xml文件中User无论是作为参数还是作为查询返回数据类型,都需要写上全限定名,实际可以写上简单类名即可,但是需要配置别名。
MyBatis框架提供了两种别名机制,一种是自定义别名,一种是内置别名。
<?xml version="1.0" encoding="UTF-8" ?><!-- dtd约束 --><!DOCTYPE configuration PUBLIC "-//MyBatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><!-- 根元素: 用于配置MyBatis --><configuration> <!-- 别名配置 --> <typeAliases> <!-- <typeAlias type="" alias=""/> 设置单个类型的别名 type: 要设置别名的数据类型(全限定名) alias : 取的别名,一般都使用类的简单名称 <package name="" /> 设置一个包的别名,推荐 --> <typeAlias type="org.cjw.pojo.User" alias="User" /> <package name="org.cjw.pojo"/> </typeAliases> <!-- 配置MyBatis的运行环境 ,可以配置多个环境,但是一次只能使用一个 default属性 : 当前使用的环境 ,使用下面环境的id 即可 --> <environments default="dev_mysql"> <!-- 环境配置 id 属性,唯一标识当前环境 --> <environment id="dev_mysql"> <!-- 配置MyBatis事务管理器 type属性 : 事物类型 JDBC 使用事务(正常提交commit,异常回滚事务 rollback) 默认 MANAGED : 不使用事务 --> <transactionManager type="JDBC"/> <!-- 配置MyBatis的数据源 type : 配置连接池 POOLED :MyBatis内置的一个连接池(默认) 后期都交给spring管理了,配置 dbcp连接池,阿里巴巴的 druid连接池 --> <dataSource type="POOLED"> <!-- 连接数据库的操作 --> <!-- 数据库驱动 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- 连接数据库的url --> <property name="url" value="jdbc:mysql://localhost:3306/users"/> <!-- 连接数据库账号 --> <property name="username" value="root"/> <!-- 连接数据库密码 --> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <!-- <mapper resource="org/cjw/mapper/UserMapper.xml"/>--> <!--指定一个配置文件--> <!--<package name="org.cjw.mapper"/>--> <!-- 指定一个包,包含多个配置文件或者配置类,推荐 --> <mapper class="org.cjw.mapper.UserMapper"/> <!-- 指定一个配置类 --> </mappers></configuration>复制代码
如果配置成功,在映射文件里面可以直接使用别名
<?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="org.cjw.mapper.UserMapper"> <!-- 新增操作 id: 当前功能的唯一标识,和接口方法同名 parameterType : 参数的类型 useGeneratedKeys:是否返回数据库生成的主键 true是/false否 keyProperty : 数据库主键对应java的pojo对象的属性 keyColumn : 数据表的主键列名 --> <insert id="insert" parameterType="User" keyProperty="id" keyColumn="id"> insert into tb_user (name, age, email, password) values (#{name}, #{age}, #{email}, #{password}); </insert> <select id="selectUserById" resultType="User"> select * from tb_user where id = #{id} </select> <!-- 多行查询 resultType : 无论是多行查询还是单行查询,返回的结果类型都是对应的JavaBean的类型 --> <select id="selectAll" resultType="User"> select * from tb_user </select> <delete id="deleteUserById"> delete from tb_user where id = #{id} </delete> <update id="updateUserById" parameterType="User"> update tb_user set name = #{name}, age = #{age}, email = #{email}, password = #{password} where id = #{id} </update></mapper>复制代码
所谓的内置别名,就是MyBatis框架自带别名。MyBatis已经将常用的数据类型
的别名声明了,所以这些内置的别名不需要配置就可以直接使用。内置的别名就是,MyBatis
框架默认已经设置的别名.
别名 |
映射的类型 |
_byte |
byte |
_long |
long |
_short |
short |
_int |
int |
_integer |
int |
_double |
double |
_float |
float |
_boolean |
boolean |
string |
java.lang.String |
byte |
Byte |
long |
Long |
short |
Short |
int |
Integer |
integer |
Integer |
double |
Double |
float |
Float |
boolean |
Boolean |
date |
java.util.Date |
decimal |
BigDecimal |
bigdecimal |
BigDecimal |
object |
Object |
map |
java.util.Map |
hashmap |
HashMap |
list |
List |
arraylist |
ArrayList |
collection |
Collection |
iterator |
Iterator |
一般开发会单独将数据库连接信息配置到db.properties配置文件中。Mybaits框架中配置文件的<properties>标签可以读取配置文件中的内容。并可以使用${key}的语法取出properties
配置文件中的value设置给框架的数据库连接参数。
jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/users?characterEncoding=utf-8jdbc.username=rootjdbc.password=root复制代码
6.2.2. 在MyBatis-config.xml主配置文件中配置
标签读取配置文件
<!-- 读取classpath下面的 数据库配置文件、 读取以后在下面连接数据库的配置中就可以使用 ${配置文件key}获取对应的数据库连接相关信息--><properties resource="db.properties" />复制代码
<dataSource type="POOLED"> <!-- 连接数据库的操作 --> <!-- 数据库驱动 --> <property name="driver" value="${jdbc.driverClassName}"/> <!-- 连接数据库的url --> <property name="url" value="${jdbc.url}"/> <!-- 连接数据库账号 --> <property name="username" value="${jdbc.username}"/> <!-- 连接数据库密码 --> <property name="password" value="${jdbc.password}"/></dataSource>复制代码
MyBatis默认设置了很多默认配置。有时候,我们需求与默认的配置的参数不一样,我们就需要修改这些默认配置的参数。
如:MyBatis对骆驼命名法的支持默认是不开启的。可以通过 mapUnderscoreToCamelCase
参数设置为true支持。表示MyBatis启动可以配置的设置。
设置参数 |
描述 |
有效值 |
默认值 |
cacheEnabled |
该配置影响的所有映射器中配置的缓存的全局开关。 |
true | false |
TRUE |
lazyLoadingEnabled |
延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 |
true | false |
FALSE |
aggressiveLazyLoading |
当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods). |
true | false |
false (true in ≤3.4.1) |
multipleResultSetsEnabled |
是否允许单一语句返回多结果集(需要兼容驱动)。 |
true | false |
TRUE |
useColumnLabel |
使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 |
true | false |
TRUE |
useGeneratedKeys |
允许 JDBC 支持自动生成主键,需要驱动兼容。如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 |
true | false |
FALSE |
autoMappingBehavior |
指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 |
NONE, PARTIAL, FULL |
PARTIAL |
autoMappingUnknownColumnBehavior |
指定发现自动映射目标未知列(或者未知属性类型)的行为。 |
NONE, WARNING, FAILING |
NONE |
defaultExecutorType |
配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 |
SIMPLE REUSE BATCH |
SIMPLE |
defaultStatementTimeout |
设置超时时间,它决定驱动等待数据库响应的秒数。 |
任意正整数 |
Not Set (null) |
defaultFetchSize |
为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。 |
任意正整数 |
Not Set (null) |
safeRowBoundsEnabled |
允许在嵌套语句中使用分页(RowBounds)。 If allow, set the false. |
true | false |
FALSE |
safeResultHandlerEnabled |
允许在嵌套语句中使用分页(ResultHandler)。 If allow, set the false. |
true | false |
TRUE |
mapUnderscoreToCamelCase |
是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 |
true | false |
FALSE |
localCacheScope |
MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 |
SESSION | STATEMENT |
SESSION |
jdbcTypeForNull |
当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 |
JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER |
OTHER |
lazyLoadTriggerMethods |
指定哪个对象的方法触发一次延迟加载。 |
A method name list separated by commas |
equals,clone,hashCode,toString |
defaultScriptingLanguage |
指定动态 SQL 生成的默认语言。 |
A type alias or fully qualified class name. |
org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
callSettersOnNulls |
指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 |
true | false |
FALSE |
returnInstanceForEmptyRow |
当返回行的所有列都是空时,MyBatis默认返回null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (i.e. collectioin and association)。(从3.4.2开始) |
true | false |
FALSE |
logPrefix |
指定 MyBatis 增加到日志名称的前缀。 |
Any String |
Not set |
logImpl |
指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 |
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING |
Not set |
proxyFactory |
指定 MyBatis 创建具有延迟加载能力的对象所用到的代理工具。 |
CGLIB | JAVASSIST |
JAVASSIST (MyBatis 3.3 or above) |
vfsImpl |
指定VFS的实现 |
自定义VFS的实现的类全限定名,以逗号分隔。 |
Not set |
useActualParamName |
允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。(从3.4.1开始) |
true | false |
TRUE |
configurationFactory |
Specifies the class that provides an instance of Configuration. The returned Configuration instance is used to load lazy properties of deserialized objects. This class must have a method with a signature static Configuration getConfiguration(). (Since: 3.2.3) |
A type alias or fully qualified class name. |
Not set |
如支持骆驼命名法
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/></settings>复制代码
MyBatis的映射配置除了使用xml配置以外,还支持注解配置sql语句。
问题:为什么有了xml配置还有注解配置。
答:MyBatis的注解开发更简洁,只需要将对应的
SQL 语句的注解标注对应的功能方法上即可,直接连XxxMapper.xml映射文件都可以省略了。本身注解开发就是Java配置的一种趋势,学习SpringBoot时候,会发现全部用纯注解配置。
MyBatis提供了下面注解进行映射文件配置
@Select 查询数据注解@Insert 插入数据注解@Delete 删除数据注解@Update 修改数据注解@Options 选项配置@Results 手动映射配置@Result @Results中的具体的某一列的映射信息配置复制代码
package org.cjw.mapper;import org.apache.ibatis.annotations.*;import org.cjw.pojo.User;import java.util.List;public interface UserMapper { /* 使用MyBatis的动态代理开发编写代码遵循四个原则 1.映射文件的namespace命名空间的值必须是对应接口的全限定名。 2.映射文件的对应功能 id值必须等于映射接口中方法的名称。 3.映射文件的参数类型必须和接口中方法的参数类型一致。 4.映射文件查询的返回结果类型必须和接口的方法的返回数据类型一致, DML操作返回的受影响的行数,除外。 */ @Insert("insert into tb_user (name, age, email, password) values (#{name}, #{age}, #{email}, #{password})") void insert(User user); @Select("select id u_id, name u_name, age u_age, email u_email, password u_password from tb_user where id = #{id}") @Results({ @Result(id = true, property = "id", column = "u_id"), @Result(property = "age", column = "u_age"), @Result(property = "name", column = "u_name"), @Result(property = "email", column = "u_email"), @Result(property = "password", column = "u_password") }) User selectUserById(Integer id); @Select("select * from tb_user") List<User> selectAll(); @Delete("delete from tb_user where id = #{id}") void deleteUserById(Integer id); @Update("update tb_user set age = #{age}, name = #{name}, email = #{email}, password = #{password} where id = #{id}") void updateUserById(User user);}复制代码
<mappers> <!-- <mapper resource="org/cjw/mapper/UserMapper.xml"/>--> <!--指定一个配置文件--> <!--<package name="org.cjw.mapper"/>--> <!-- 指定一个包,包含多个配置文件或者配置类,推荐 --> <mapper class="org.cjw.mapper.UserMapper"/> <!-- 指定一个配置类 --></mappers>复制代码
该映射类的xml配置文件不能放置到该映射类同包环境下,否则会报映射语句已经包含的异常。
MyBatis 默认情况下是不支持传入多个参数的 ,只能传入一个参数。
所谓的传入参数指的是MyBatis操作(<insert><delete><update><select>)的传入参数。
方案1:将这些参数封装到一个对象里面(JavaBean/Map),再传入。
方案2:给参数设置一个@Param注解支持,而且多参数的类型要统一。
问题:为什么不支持多个参数?
因为Java语法1.7以前,是不能通过反射技术获得方法的参数名的。
解决方案使用 @Param 参数注解。
@Select("select * from tb_user where name = #{name} and password = #{password}")User login(User user);@Select("select * from tb_user where name = #{name} and password = #{password}")User login2(Map<String, Object> map);@Select("select * from tb_user where name = #{name} and password = #{password}")User login3(@Param("name") String name, @Param("password") String password);复制代码
@Testpublic void testLogin() { SqlSession session = MyBatisUtil.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setName("zhangsan"); user.setPassword("zhangsan123123"); User loginUser = userMapper.login(user); System.out.println(loginUser.getName());}@Testpublic void testLogin2() { SqlSession session = MyBatisUtil.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("name", "zhangsan"); map.put("password", "zhangsan123123"); User loginUser = userMapper.login2(map); System.out.println(loginUser.getName());}@Testpublic void testLogin3() { SqlSession session = MyBatisUtil.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); User loginUser = userMapper.login3("zhangsan", "zhangsan123123"); System.out.println(loginUser.getName());}复制代码
在MyBatis框架中支持两种OGNL语法#{}${}
#{}基于JDBC的PreparedStatement类,SQL语句参数使用?占位符,在运行阶段动态设置参数,但是?不能作为表名。预编译语句对象的SQL语句只能操作DML和DQL语句,不能操作DDL语句。
1.#{}表示设置预编译的参数,就是?的参数,所以如果要不固定的表名不能使用#{},只能使用${}
2.${}直接把值输出来,直接把参数拼接到SQL语句中.而#{}是使用?来代替.所以${}是不安全的。
3.${}只能获得参数池的值,而#{}可以获得方法的参数值,也可以获得参数池的值,如果使用${}获得参数的值,这个参数必须要加上@Param。如果非必要情况,不要使用${}。
问题:那么${}有什么用呢?
答:注意基于JDBC的接口的原来的表名是不可以使用?的,?只能用于传入的参数。如果操作的涉及表名这些非参数的数据时,需要使用${}。
import org.apache.ibatis.annotations.Param; public interface UserMapper { /** * 动态删除数据库中指定表名 * @param tableName 表名 * @return */ int dropTable(@Param("tableName")String tableName);} 复制代码
映射文件:
<?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="org.cjws.mybatis.mapper.UserMapper"> <!-- 使用#{} 不能使用在表名操作 --> <delete id="dropTable" parameterType="String"> <!-- drop table #{tableName} --> drop table ${tableName} </delete></mapper>复制代码
使用此种方法无法删除数据库表
9.2.2. 使用${}