MyBatis 本是apache的一个开源项目iBatis, 2010年 迁移到了google code,并且改名为MyBatis 。是一个基于Java的持久层ORM关系映射框架
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集(dao层零实现)。
MyBatis 使用简单的 XML 或注解来配置和映射基本体,将 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
中文官网:
链接
对象模型表示的对象映射到基于SQL 的关系模型数据库结构中去。这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的SQL 语句打交道,只需简单的操作实体对象的属性和方法。
Resources:资源类,用于读取总配置文件
SqlSessionFactoryBuilder:会话工厂构造类,通过读取的总配置文件构建会话工厂
SqlSessionFactory:会话工厂
SqlSession:会话,就是操作数据库的操作类
https://github.com/mybatis/mybatis-3/releases
mybatis的 dao零实现操作数据库
-- 学生信息表
CREATE TABLE tb_student
(
stuId bigint NOT NULL AUTO_INCREMENT COMMENT '学生编号',
stuName varchar(50) COMMENT '学生名字',
stuAge int COMMENT '学生年龄',
stuPassword varchar(50) COMMENT '密码',
PRIMARY KEY (stu_id)
) COMMENT = '学生信息表'
新建一个java项目并导入包
新建mybatis总配置模板文件
1、file—setting,左上角输入template
2、在左侧栏找到File And Code Templates
3、中间选中Files
4、点击+号,添加模板
5、输入模板名字:Name:mybatis-cfg.xml (name可以自定义)
6、后缀名extension:xml
7、在面板中间输入内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<configuration>
</configuration>
8、把enable live Template(激活模板)勾选上
9、点击Apply—ok
10、选中模板,然后输入xml文件名字mybatis.cfg.xml
-注意:Mybatis的DTD的Public ID没有写在DTD文件里面,可以在官方文档里面找到
–以后,任何框架如果没有在DTD文件提供Public Id 的都去找官方文档。
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
configuration>
db.properties:
#mysql数据源
mysql.driver=com.mysql.jdbc.Driver
#使用默认的本地ip和默认端口号
mysql.url=jdbc:mysql:///mybatis
mysql.username=root
mysql.password=123456
public class MybatisUtils {
// 注意:基于如果出现多个会话工厂,可能导致事务不同步的问题,所以我们一个项目只使用一个会话工厂
public static final SqlSessionFactory SSF = createSqlSessionFactory();
// 需求:实现同一条线程,使用的session是相同的。线程绑定,
// 创建一个线程绑定变量,将变量放在该对象里面,表示对象同一条线程共享
private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
// 1.获得会话工厂
private static SqlSessionFactory createSqlSessionFactory() {
try {
// 1.返回一个Reader对象
Reader reader = Resources.getResourceAsReader("mybatis-cfg.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(reader);
return sessionFactory;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 2.获得操作对象,SqlSession对象
public static SqlSession getSqlSession() {
//1.判断线程变量里面是否已经有值
if (threadLocal.get() == null) {
//2.如果没有值,那么创建一个session对象设置在线程变量里面
SqlSession session = SSF.openSession();
threadLocal.set(session);
}
//3.返回线程变量里面的session对象
return threadLocal.get();
}
public static void main(String[] args) {
//同一条线程。对象一样
//注意事项:如果对象是一个静态的属性的,意味着,整个系统共用一个对象
//如果放在ThreadLocal对象里面,仅仅是当前线程共用该对象
System.out.println(MybatisUtils.getSqlSession());
System.out.println(MybatisUtils.getSqlSession());
}
}
Thread与ThreadLocal的伪代码关联关系
public class Student {
private String stuId;//BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '学生编号',
private String stuName;//VARCHAR(50) NULL DEFAULT NULL COMMENT '学生名字',
private String stuAge;//INT(11) NULL DEFAULT NULL COMMENT '学生年龄',
private String stuPassword;//VARCHAR(50) NULL DEFAULT NULL COMMENT '密码',
public String getStuId() {
return stuId;
}
public void setStuId(String stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuAge() {
return stuAge;
}
public void setStuAge(String stuAge) {
this.stuAge = stuAge;
}
public String getStuPassword() {
return stuPassword;
}
public void setStuPassword(String stuPassword) {
this.stuPassword = stuPassword;
}
}
public interface StudentMapper {
//需求:实现插入数据到student表
//注意:如果是增删改操作,返回的类型必须是int类型
//返回的是操作影响的行数。
int insert(Student student);
}
创建一个mybatis-mapper.xml模板文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<!-- 注意事项:使用映射接口的配置方式,namespace必须指向接口的类全名 -->
<mapper namespace="cn.mapper.StudentMapper">
<!--
useGeneratedKeys:作用打开支持ID回填,设置为true
keyColumn:设置ID回填,ID对象数据库的字段名
keyProperty:设置ID回填到JavaBean对应的属性名
-->
<insert id="insert" useGeneratedKeys="true" keyColumn="stuId" keyProperty="stuId" >
<!-- 注意:如果传递过来的是一个JavaBean对象,那么设置的属性名为,set方法对应的属性名。如:setStuName 对应的是 stuName
-->
INSERT INTO tb_student (stuName, stuAge, stuPassword) VALUES (#{
stuName}, #{
stuAge}, #{
stuPassword})
</insert>
</mapper>
<mappers>
<mapper resource="cn/mapper/xml/StudentMapper.xml"/>
mappers>
public class StudentMapperTest {
@Test
public void insert(){
//1.获得操作对象,session
SqlSession session = MybatisUtils.getSqlSession();
//2.获得操作接口的动态对象
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
Student student=new Student();
student.setStuName("陈七");
//3.插入对象
int count = studentMapper.insert(student);
//4.提交事务
session.commit();
//5.关闭
session.close();
System.out.println("返回值:"+count);
//需求:实现ID回填,就是插入数据后要将数据库的ID设置在实体类对象里面
System.out.println("ID:"+student.getStuId());
}
}
<configuration>
<properties resource="db.properties">properties>
<environments default="default-msql">
<environment id="default-msql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="cn/mapper/xml/StudentMapper.xml"/>
mappers>
configuration>
果然实现的操作层的零实现!!!
a.MyBatis应用程序Configuration对象根据XML配置文件或注解创建SqlSessionFactory工厂,获取一个SqlSession,加载SQL配置信息,生成一个个MappedStatement对象(包括传入参数映射配置、执行的sql语句、结果映射配置),并存储在内存中,
b.SQL解析,SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句
(调用方法时,会接收到SQL的ID和传入对象,MyBatis会根据SQL的ID找到对应的MappedStatement,然后根据传入的参数对象对MappedStatement进行解析,解析后可以得到最终需要执行的SQL语句和参数)
c.SQL执行,完成对数据的增删改查,得到数据库操作结果
d.结果映射将操作结果按照映射配置进行转换,转换成HashMap、JavaBean等
e.事务提交,用完之后关闭SqlSession,返回结果。
注意:文件名必须为log4j.properties
#--------console-----------
log4j.appender.myconsole=org.apache.log4j.ConsoleAppender
log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout
#--------HTML-----------
log4j.appender.myfile=org.apache.log4j.FileAppender
log4j.appender.myfile.File=D\:\\error.html
log4j.appender.myfile.layout=org.apache.log4j.HTMLLayout
#默认设置,用于指定默认的记录的日志级别
#日志级别:debug info warm error fatal(致命错误)
log4j.rootLogger=info,myfile,myconsole
# 输出 mybatis 的sql语句与参数 指定mapper接口所在的位置的输出级别即可
# log4j.logger.mapper接口所在的包名=TRACE
log4j.logger.com.mapper=TRACE
CRUD:create read update del
示例的SQL代码
CREATE TABLE `student` (
`sid` int(11) NOT NULL AUTO_INCREMENT,
`aid` int(11) DEFAULT NULL,
`sname` varchar(50) DEFAULT NULL,
`sex` char(3) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
就是Mybatis支持三种风格的操作代码.
就是使用接口+XML映射文件直接操作数据库。代码查看上面的入门示例代码!
元数据:就是启动项目是必须的数据.
为什么现在的框架都使用注解来代替xml文件呢?
答:就是因为xml配置文件不是编程语言的语法,所以无法断点调试.使用注解,注解是Java编程语言的语法,断点调试时,可以尽可能排除配置文件的出错
配置步骤:
<configuration>
<environments default="default-msql">
<environment id="default-msql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/school"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<mapper class="cn.mapper.StudentMapper"/>
mappers>
configuration>
public class MybatisUtils {
// 注意:基于如果出现多个会话工厂,可能导致事务不同步的问题,所以我们一个项目只使用一个会话工厂
public static final SqlSessionFactory SSF = createSqlSessionFactory();
// 需求:实现同一条线程,使用的session是相同的。线程绑定,
// 创建一个线程绑定变量,将变量放在该对象里面,表示对象同一条线程共享
private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
// 1.获得会话工厂
private static SqlSessionFactory createSqlSessionFactory() {
try {
// 1.返回一个Reader对象
Reader reader = Resources.getResourceAsReader("mybatis-cfg.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(reader);
return sessionFactory;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 2.获得操作对象,SqlSession对象
public static SqlSession getSqlSession() {
//1.判断线程变量里面是否已经有值
if (threadLocal.get() == null) {
//2.如果没有值,那么创建一个session对象设置在线程变量里面
SqlSession session = SSF.openSession();
threadLocal.set(session);
}
//3.返回线程变量里面的session对象
return threadLocal.get();
}
public static void main(String[] args) {
//同一条线程。对象一样
//注意事项:如果对象是一个静态的属性的,意味着,整个系统共用一个对象
//如果放在ThreadLocal对象里面,仅仅是当前线程共用该对象
System.out.println(MybatisUtils.getSqlSession());
System.out.println(MybatisUtils.getSqlSession());
}
}
public class Student {
private Integer sid;//int(11) not null auto_increment comment '编号',
private Integer aid;//int(11) null default '0',
private String sname;//varchar(50) null default null comment '姓名',
private String sex;//char(3) null default null comment '性别',
private Date birthday;//date null default null comment '生日',
private Integer age;//int(11) null default null comment '年龄',
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public Integer getAid() {
return aid;
}
public void setAid(Integer aid) {
this.aid = aid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
System.out.println("-输出名字-"+sname);
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public interface StudentMapper {
/**
* 插入记录
* @param entity
* @return
*/
@Insert(value="INSERT INTO student(AID, SNAME, SEX, BIRTHDAY, AGE) VALUES (#{sid}, #{sname}, #{sex}, #{birthday}, #{age})")
int insert(Student entity);
/**
* 删除记录
* @param sid
* @return
*/
@Delete(value="DELETE FROM student WHERE SID=#{sid}")
int deleteById(int sid);
/**
* 更新记录
* @param entity
* @return
*/
@Update(value="UPDATE student SET AID=#{aid},SNAME=#{sname},SEX=#{sex},BIRTHDAY=#{birthday},AGE=#{age} WHERE SID=#{sid}")
int update(Student entity);
/**
* 查询所有的记录
* @return
*/
@Select(value="SELECT * FROM student")
List<Student> findAll();
}
public class StudentMapperTest {
/* @Test
public void insert() {
try {
//1.获得操作对象
SqlSession session = DbUtils.getSession();
//2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
Student student = new Student();
student.setSname("王五");
student.setSex("男");
//调用接口操作数据库
studentMapper.insert(student);
//提交
session.commit();
session.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
/* @Test
public void deleteById(){
//1.获得操作对象
SqlSession session = DbUtils.getSession();
//2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
int count=studentMapper.deleteById(1);
System.out.println(count);
session.commit();
session.close();
}*/
/* @Test
public void update(){
//1.获得操作对象
SqlSession session = DbUtils.getSession();
//2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
Student entity=new Student();
entity.setSname("赵六");
entity.setSex("男");
entity.setAge(20);
entity.setBirthday(new Date());
entity.setSid(2);
//更新记录
int count=studentMapper.update(entity);
System.out.println(count);
session.commit();
session.close();
}*/
@Test
public void findAll(){
//1.获得操作对象
SqlSession session = DbUtils.getSession();
//2.使用session.获得映射接口的代理对象,这个代理对象是mybatis通过StudentMapper.xml创建的
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List<Student> list = studentMapper.findAll();
for(Student s:list){
System.out.print("姓名:"+s.getSname());
System.out.print(",年龄:"+s.getAge());
System.out.println(",生日:"+s.getBirthday());
}
session.commit();
session.close();
}
}
Mybatis也支持基于DAO方式的操作,这种方式是继承ibatis的,方便原来使用ibatis的程序员可以平滑过渡到Mybatis.现在开发很少使用了.
这种开发的方式就是:创建一个映射文件,定义一个任意的命令空间名,通过SqlSession提供的insert,delete,update,selectList等方法操作指定命名空间下的操作.
操作字符串的格式为: 命名空间.操作ID
开发步骤
<configuration>
<environments default="default-msql">
<environment id="default-msql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/school"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<mapper class="cn.mapper.StudentMapper"/>
mappers>
configuration>
创建一个MybatisUtils工具类获得SqlSession操作对象
public class MybatisUtils {
// 注意:基于如果出现多个会话工厂,可能导致事务不同步的问题,所以我们一个项目只使用一个会话工厂
public static final SqlSessionFactory SSF = createSqlSessionFactory();
// 需求:实现同一条线程,使用的session是相同的。线程绑定,
// 创建一个线程绑定变量,将变量放在该对象里面,表示对象同一条线程共享
private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
// 1.获得会话工厂
private static SqlSessionFactory createSqlSessionFactory() {
try {
// 1.返回一个Reader对象
Reader reader = Resources.getResourceAsReader("mybatis-cfg.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(reader);
return sessionFactory;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 2.获得操作对象,SqlSession对象
public static SqlSession getSqlSession() {
//1.判断线程变量里面是否已经有值
if (threadLocal.get() == null) {
//2.如果没有值,那么创建一个session对象设置在线程变量里面
SqlSession session = SSF.openSession();
threadLocal.set(session);
}
//3.返回线程变量里面的session对象
return threadLocal.get();
}
public static void main(String[] args) {
//同一条线程。对象一样
//注意事项:如果对象是一个静态的属性的,意味着,整个系统共用一个对象
//如果放在ThreadLocal对象里面,仅仅是当前线程共用该对象
System.out.println(MybatisUtils.getSqlSession());
System.out.println(MybatisUtils.getSqlSession());
}
}
//ctrl+shift+y 大写转小写
public class Student {
private Integer sid;//int(11) not null auto_increment comment '编号',
private Integer aid;//int(11) null default '0',
private String sname;//varchar(50) null default null comment '姓名',
private String sex;//char(3) null default null comment '性别',
private Date birthday;//date null default null comment '生日',
private Integer age;//int(11) null default null comment '年龄',
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public Integer getAid() {
return aid;
}
public void setAid(Integer aid) {
this.aid = aid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
System.out.println("-输出名字-"+sname);
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
<mapper namespace="studentDAO">
<insert id="insert">
INSERT INTO student(AID, SNAME, SEX, BIRTHDAY, AGE) VALUES (#{sid}, #{sname}, #{sex}, #{birthday}, #{age})
insert>
<delete id="deleteById">
DELETE FROM student WHERE SID=#{sid}
delete>
<update id="update">
UPDATE student SET AID=#{aid},SNAME=#{sname},SEX=#{sex},BIRTHDAY=#{birthday},AGE=#{age} WHERE SID=#{sid}
update>
<select resultType="cn.entity.Student" id="findAll">
SELECT * FROM student
select>
mapper>
public class StudentDAO {
/**
* 插入数据
* @param entity
* @return
*/
public int insert(Student entity){
//1.获得操作类对象
SqlSession session = DbUtils.getSession();
//2.操作
//session.insert(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
//格式为:命名空间.操作的ID,如:studentDAO.insert
int count=session.insert("studentDAO.insert", entity);
session.commit();
session.close();
return count;
}
/**
* 删除记录
* @param entity
* @return
*/
public int deleteById(int sid){
//1.获得操作类对象
SqlSession session = DbUtils.getSession();
//2.操作
//session.insert(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
//格式为:命名空间.操作的ID,如:studentDAO.insert
//增删改,的语法是一样,Mybatis并不知道你做的事增删改,它只知道你执行的是SQL语句.
//但一定要注意,虽然增删改的标签的功能一样,还是建议增使用insert,删使用delete,改使用update
//session.delete(statement),这个没有参数的删除
int count=session.delete("studentDAO.deleteById", sid);
session.commit();
session.close();
return count;
}
/**
* 更新记录
* @param entity
* @return
*/
public int update(Student entity){
//1.获得操作类对象
SqlSession session = DbUtils.getSession();
//2.操作
//session.update(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
//格式为:命名空间.操作的ID,如:studentDAO.update
int count=session.update("studentDAO.update", entity);
session.commit();
session.close();
return count;
}
public List<Student> findAll(){
//1.获得操作类对象
SqlSession session = DbUtils.getSession();
//2.操作
//session.update(statement); 没有操作参数的插入,如果没有传入的参数,意味着插入的数据只能写在xml映射文件里面
//格式为:命名空间.操作的ID,如:studentDAO.update
//没有返回参数的
List<Student> selectList = session.selectList("studentDAO.findAll");
session.commit();
session.close();
return selectList;
}
}
public class StudentDAOTest {
/* @Test
public void insert() {
try {
StudentDAO studentDAO = new StudentDAO();
Student entity=new Student();
entity.setSname("陈七");
entity.setBirthday(new Date());
entity.setAge(21);
int count=studentDAO.insert(entity);
System.out.println(count);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
/* @Test
public void deleteById(){
StudentDAO studentDAO = new StudentDAO();
int count=studentDAO.deleteById(4);
System.out.println(count);
}*/
/* @Test
public void update(){
StudentDAO studentDAO = new StudentDAO();
Student entity=new Student();
entity.setSname("李四");
entity.setBirthday(new Date());
entity.setAge(21);
entity.setSid(2);
int count=studentDAO.update(entity);
System.out.println(count);
}*/
//ctrl+shift+/
@Test
public void findAll(){
StudentDAO studentDAO = new StudentDAO();
List<Student> list = studentDAO.findAll();
for(Student s:list){
System.out.print("姓名:"+s.getSname());
System.out.print(",年龄:"+s.getAge());
System.out.println(",生日:"+s.getBirthday());
}
}
}
:环境集便签,就是用于配置数据库的连接信息的
:用于配置具体环境参数
:配置使用的事务类型,JDBC
:配置数据源的参数,具体参数参看PooledDataSource的set方法
:配置属性
:配置映射文件信息的
:配置具体指定的mapper文件 class:配置使用注解时指定有注解的映射接口
resource:指定映射文件
:mybatis对propertis文件的支持
:用于配置别名
:用于配置自定义类型处理器.
:配置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次
<configuration>
<typeAliases>
<typeAlias type="cn.entity.Student" alias="student"/>
typeAliases>
<environments default="default-msql">
<environment id="default-msql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/school"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mybatis-mapper/StudentMapper.xml"/>
mappers>
configuration>
如果配置成功,在映射文件里面可以直接使用别名
<select resultType="student" id="findAll">
SELECT * FROM student
select>
别名方式2:去掉包名
<configuration>
<typeAliases>
<package name="cn.entity"/>
typeAliases>
<environments default="default-msql">
<environment id="default-msql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/school"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mybatis-mapper/StudentMapper.xml"/>
mappers>
configuration>
对应的映射文件的配置
<select resultType="Student" id="findAll">
SELECT * FROM student
select>
xml
所谓的内置别名,就是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 | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
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 |
NONE: 不做任何反应 | |||
WARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior’的日志等级必须设置为 WARN) | |||
FAILING: 映射失败 (抛出 SqlSessionException) | |||
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操作()的传入参数.
Mybatis默认情况下是不支持传入多个参数的.只能传入一个参数.
方案1:将这些参数封装到一个对象里面(JavaBean/Map),再传入.
方案2:给参数设置一个@Param注解支持
为什么不支持多个参数?
因为Java语法1.7以前.是不能通过反射技术获得方法的参数名的.
所以Mybatis只能通过参数的类型来获得参数值.
但Java语法上一个方法可以有多个相同类型的参数.
导致如果Mybatis支持的方法有多个相同的参数时.那么就无法判断参数是哪个参数值了.
所有Mybatis映射接口操作的方法只能默认支持一个参数****.
因为使用的是方法的参数的类型来获得参数的,所以在配置文件里面如果获得的值就是方法的参数的值,其实#{随便写},获得的都是这个方法int deleteById(int sid);
结论:
1.默认情况,所有Mybatis映射接口操作的方法只能默认支持一个参数.
2.操作方法的参数是通过类型来取值的.而不是参数名
Mybatis是通过一个参数池概念来支持多参数的.
要使用注解@Param(value=”key”)来将参数放在参数池里面
接口代码
/**
* 分页查询
* @param index
* @param pageNum
* @return
*/
List<Student> findAllToPage(@Param(value="index")int index ,@Param(value="pageNum") int pageNum);
映射文件代码
<select id="findAllToPage" resultType="Student">
SELECT * FROM student limit #{index},#{pageNum}
select>
#{}基于JDBC的PreparedStatement类,?不能作为表名.
${}可以放表名
<!-- 通过一个操作创建一个表 -->
<delete id="dropTacle">
<!-- PreparedStatement决定了表名不能是?,?必须SQL的参数 -->
drop table ${
tableName}
</delete>
/**
* 删除表
* @param tableName
* @return
*/
int dropTacle(@Param("tableName") String tableName);
a.#{}表示设置预编译的参数,就是?的参数,所以如果要不固定的表名不能使用#{},只能使用${}
b.KaTeX parse error: Expected 'EOF', got '#' at position 12: {}直接把值输出来.而#̲{]是使用?来代替. 所以{}是不安全的.
c.${}只能获得参数池的值,而#{}可以获得方法的参数值,也可以获得参数池的值,如果使用 ${}获得参数的值,这个参数必须要加上@Param
示例:
/**
* 删除记录
* @param sid
* @return
*/
int deleteById(@Param("sid") int sid);
<delete id="deleteById">
DELETE FROM student WHERE SID=${sid}
delete>
如果非必要情况,不要使用${}
问题:那${}有什么用呢?
答:注意基于JDBC的接口的原来的表名是不可以使用?的,?只能用于传入的参数。
如果操作的涉及表名这些非参数的 数据时,需要使用${}
有时候,返回的数据的字段和程序的实体类是不同的.Mybatis提供了一个resultMap来手工的配置对应的关系.
ResultMap的作用:
就是用于手工关联实体类与数据库表的字段的关联关系
<mapper namespace="cn.mapper.StudentMapper">
<resultMap type="Student" id="studentResultMap" autoMapping="true">
<id property="sid" column="sid"/>
<result property="sname" column="NAME"/>
resultMap>
<insert id="insert">
INSERT INTO student(SNAME, AGE) VALUES (#{sname},#{age})
insert>
<delete id="deleteById">
DELETE FROM student WHERE SID=${sid}
delete>
<update id="update">
UPDATE student SET AID=#{aid},SNAME=#{sname},SEX=#{sex},BIRTHDAY=#{birthday},AGE=#{age} WHERE SID=#{sid}
update>
<select resultMap="studentResultMap" id="findAll">
SELECT * FROM student
select>
<select resultType="map" id="findAllByMap">
SELECT * FROM student
select>
<select id="findAllToPage" resultType="Student">
SELECT * FROM student limit ${index},${pageNum}
select>
<insert id="dropTacle">
drop table ${tableName}
insert>
mapper>
a.Mybatis是什么
答:Mybatis就是一个持久层框架。意味着它的功能就是增删改查
b. Mybatis实现了什么理念?
答:操作层(持久层)的零实现!!!
c. 什么是零实现?
答:持久层不需要编写实现类,只要接口就可以操作数据库。
d.零实现有什么好处!?
答:大大的减少了持久层的代码,从而提高了开发的效率。Mybatis为开发效率而生!!
e.Mybatis是通过什么方式来实现零实现的呢?
答:通过动态代理技术,实现了接口获得动态对象
通过反射技术,获得XML配置的数据创建多态类对象
f. Mybatis是一个先操作,后映射的框架。
意思就是说,Mybatis是先通过SQL将数据查询出来,将映射到具体的实体类或者Map上面。
映射实体类的方式有三种:
a. 通过手工设置SQL语句的别名与实体类的属性名一一对应
b. 通过Mybatis的自动转换驼峰命名法的方式设置数据表的字段名与属性名的一一对应
c. 通过标签设置表的字段名与实体类的属性名的一一对应
–重点:配置流程图—
三种配置:
a. 配置文件加映射接口的配置(现在)
b. 注解加映射接口的配置(未来)
c. 配置文件加DAO的配置(过去)【可选】