1. MyBatis 概述

  1. MyBatis 是一个半自动化的持久层框架;

    • 核心SQL,开发人员可以进行优化;
    • SQL和Java编码分开,功能边界清晰,一个专注业务,一个专注数据;
  2. JDBC:
    • SQL 语句夹在Java代码块里,耦合度高,导致硬编码内伤;
    • 维护不易且实际开发需求中SQL是有变化,频繁修改的情况多见;
  3. Hibernate 和 JPA
    • 长难复杂SQL,对于Hibernate而言处理也不容易;
    • 内部自动生产的SQL,不容易做特殊优化;
    • 基于全映射的全自动框架,大量字段的POJO进行部分映射时,比较困难;从而导致数据库性能下降;

2. MyBatis 入门程序搭建

// 创建 Java Project

// 1. 导入 jar 包(3个)
/*
* log4j-1.2.17(用来在控制台打印 SQL 语句)
* mybatis-3.4.1
* mysql-connector-java (SQL 驱动包)
*/ // 2. 创建 Bean
// cn.itcast.mybatis.bean.Employee.java
public class Employee{
private Integer id;
private String lastName;
private String email;
// 以数字 0 表示男性, 1 表示女性
private Integer gender; // getter 和 setter 略
} // 3. 配置文件, 存放在 conf 文件夹下
// 创建 Source Folder, 名称为 conf // log4j.xml
(具体见"参考资料"中链接) // mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments> <!-- 将写好的SQL映射文件,一定要注册到全局配置文件中 -->
<mappers>
<mapper resource="EmployeeMapper.xml" />
</mappers>
</configuration> // EmployeeMapper.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="cn.itcast.mybatis.EmployeeMapper"> <!-- namespace: 命名空间, id: 表示唯一标识, resultType: 返回值类型 -->
<select id="selectEmp" resultType="cn.itcast.mybatis.bean.Employee"> <!-- 数据库中 last_name, Bean 类中 lastName, 以下相当于用别名查询 -->
<!-- #{id} 表示从传递过来的参数中,获取id值 -->
select id,last_name lastName,email,gender from tbl_employee where id = #{id}
</select>
</mapper> // 4. 编写测试类
public class MyBatisTest{ // 1. 根据mybatis的配置文件(全局配置文件),创建一个 SqlSessionFactory 对象; @Test
public void test() throws IOException{
String resource = "mybatis-config.xml";
InputStream inputStream = Resorces.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream); // 2. 获取 SqlSession 实例, 使用该实例执行数据库的增删改查;
// 一个sqlSession,就是代表和数据库的一次会话,用完需要关闭;
// sqlSession 是非线程安全的,每次使用都应该去获取新的对象;
SqlSession openSession = sqlSessionFactory.openSession(); try{
// selectOne(String statement, Object parameter) 参数说明:
// statement: sql的唯一标识, 建议写法: 命名空间+id
// parameter: 执行 sql 要用的参数
Employee employee =
openSession.selectOne("cn.itcast.mybatis.EmployeeMapper.selectEmp",1);
System.out.println(employee);
}finally{
openSession.close();
}
}
} // 升级版本: 接口式编程
// 使用接口,实现增删改查
// 创建 cn.itcast.mybatis.dao.EmployeeMapper.java 接口
public interface EmployeeMapper{ // 按id查询
public Employee getEmpById(Integer id);
} // 修改 EmployeeMapper.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="cn.itcast.mybatis.dao.EmployeeMapper"> <!--
namespace: 命名空间,指定为接口的全类名;
id: 表示唯一标识,接口中的方法名;
resultType: 返回值类型
--> <select id="getEmpById" resultType="cn.itcast.mybatis.bean.Employee"> <!-- 数据库中 last_name, Bean 类中 lastName, 以下相当于用别名查询 -->
<!-- #{id} 表示从传递过来的参数中,获取id值 -->
select id,last_name lastName,email,gender from tbl_employee where id = #{id}
</select>
</mapper> // 修改测试类
public class MyBatisTest{ // 获取 sqlSessionFactory 对象的方法
public SqlSessionFactory getSqlSessionFactory() throws IOException{
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
} @Test
public test02() throws IOException{
// 1. 获取 sqlSessionFactory 对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2. 获取 SqlSession 实例
SqlSession openSession = sqlSessionFactory.openSession(); try{
// 3. 获取接口的实现类对象
// mybatis 会为接口自动创建一个代理对象, 代理对象去执行增删改查方法
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); // 调用接口实现类的方法
Employee employee = mapper.getEmpById(1);
System.out.println(employee);
}finally{
// 4. 关闭 SqlSession
openSession.close();
}
}
}

3. MyBatis 全局配置文件

3.1 常用标签介绍

  • <properties>: 引入外部 properties 配置文件的内容;

    • resource属性: 引入类路径下的资源;
    • url属性: 引入网络路径或者磁盘路径下的资源;
  • <settings>: 包含了很多重要的设置项
  • <typeAliases>: 别名处理器,可以给 java 类型起别名,方便使用;
  • <typeHandlers>: 类型处理器, 处理数据库类型与Java类型的转换;
  • <plugins>
  • <environments>: mybatis 可以配置多种环境, default 的值对应<environment>中的 id 值;
  • <databaseIdProvider>: 设置数据库厂商;
  • <mappers>: 将sql映射文件注册到全局配置文件中;
// 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> <properties resource="dbconfig.properties"></properties> <!-- 是否开启驼峰命名:即从数据库列名"a_column"到Java属性名 "aColumn" 的类似映射 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings> <!-- typeAliase, 别名处理器, 别名不区分大小写 -->
<typeAliases>
<!-- 默认别名就是类名小写: employee; 也可以使用 alias 指定新的别名 -->
<typeAlias type="cn.itcast.mybatis.bean.Employee"/> <!-- package: 为某个包下的所有类批量起别名
name: 指定包名(为当前包以及下面所有的后代包的每一个类都起一个默认别名(类名小写)) 批量起别名的情况下, 使用 @Alias 注解为某个类型指定新的别名;
-->
<package name="cn.itcast.mybatis.bean"/>
</typeAliases> <environments default="development">
<environment id="development">
<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> <!-- 将写好的SQL映射文件,一定要注册到全局配置文件中
注册配置文件:
resource: 引入类路径下的sql映射文件;
url: 引用网络路径或者磁盘路径下的sql映射文件;
也可以注册接口:
class: 注册接口
1. 有 sql 映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下;
2. 没有 sql 映射文件,所有的 sql 都是利用注解写在接口上;
备注:
比较重要,复杂的 Dao 接口,使用 sql 映射文件;
简单的Dao接口为了开发方便,可以使用注解;
-->
<mappers>
<mapper resource="EmployeeMapper.xml" />
<mapper class="cn.itcast.mybatis.bean.EmployeeMapper"/>
</mappers>
</configuration> // dbconfig.properties 配置文件
jdbc.driver=com.mysql.jdbc.driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root

4. MyBatis 映射文件

// 映射增删改查语句

// EmployeeMapper.java 接口
public interface EmployeeMapper{ // 单个参数
public Employee getEmpById(Integer id); public void addEmp(Employee employee); public void updateEmp(Employee employee); public void deleteEmpById(Integer id); // 备注:
// MyBatis 允许增删改直接定义以下返回值: Integer, Long, Boolean, void
// 表示增删改影响的行数, 如果行数大于0, Boolean 值为 true;
// 例如: public boolean updateEmp(Employee employee);
} // EmployeeMapper.xml 配置文件
<mapper namespace="cn.itcast.mybatis.dao.EmployeeMapper"> <!-- 查询方法 -->
<select id="getEmpById" resultType="cn.itcast.mybatis.bean.Employee">
select * from tbl_employee where id="#{id}"
</select> <!-- 添加方法
自增主键值的获取: MyBatis 也是利用 statement.getGeneratedKeys(); 不过,需要配置
useGeneratedKeys="true": 表示使用自增主键获取主键值策略
keyProperty: 指定对应的主键属性,也就是MyBatis获取到主键值以后,将这个值封装给 JavaBean 的哪个属性
-->
<insert id="addEmp" useGeneratedKeys="true" keyProperty="id">
insert into tbl_employee(last_name,email,gender)
values(#{lastName},#{email},#{gender})
</insert> <!--
Oracle 不支持自增; Oracle 使用序列来模拟自增;
每次插入的数据的主键,是从序列中拿到的值,
Oracle 数据库中获取主键的配置:
-->
<insert id="addEmp" databaseId="oracle">
<!--
keyProperty: 查出的主键值封装给 JavaBean 的哪个属性
order="BEFORE": 当前sql在插入sql之前运行
resultType: 查询出数据的返回值类型
-->
<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
<!-- 查询主键的sql语句 -->
select EMPLOYEES_SEQ.nextval from dual
</selectKey> <!-- 插入数据时的主键,是从序列中拿到的 -->
insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL)
values(#{id},#{lastName},#{email})
</insert> <!-- 更新方法 -->
<update id="updateEmp">
update tbl_employee
set last_name=#{lastName},email=#{email},gender=#{gender}
where id=#{id}
</update> <!-- 删除方法 -->
<delete id="deleteEmpById">
delete from tbl_employee where id=#{id}
</delete> </mapper> // 编写测试类
public class MyBatisTest{
// 1. 获取 SqlSessionFactory 方法(同上) // 2. 测试方法
@Test
public void test01() throws IOException{
// 1. 获取 SqlSessionFactory 对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2. 获取 SqlSession 实例
// sqlSessionFactory.openSession(); 该实例需要手动提交数据
// sqlSessionFactory.openSession(true); 该实例可以自动提交数据
SqlSession openSession = sqlSessionFactory.openSession(); try{
// 3. 获取接口的实现类对象
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); // 添加方法
Employee employee = new Employee(null,"zhangsan","zhangsan@163.com","1");
mapper.addEmp(employee);
// 输出主键值
System.out.println(employee.getId()); // 更新方法
Employee employee = new Employee(1,"lisi","lisi@163.com","1");
mapper.updateEmp(employee); // 删除方法
mapper.deleteEmpById(2); // 4. 手动提交
openSession.commit();
}finally{
// 5. 关闭资源
openSession.close();
}
}
}

4.1 MyBatis 映射文件的参数处理

// 示例: 查询方法中带有多个参数

// EmployeeMapper.java 接口
public interface EmployeeMapper{ // 多个参数
public Employee getEmpByIdAndLastName(Integer id, String lastName);
} // EmployeeMapper.xml 配置文件
<mapper namespace="cn.itcast.mybatis.dao.EmployeeMapper"> <!-- 查询方法(多个参数)
出现异常: org.apache.ibatis.binding.BindingException:
Parameter 'id' not found. Available parameters are [0, 1, param1, param2]
-->
<select id="getEmpByIdAndLastName" resultType="cn.itcast.mybatis.bean.Employee">
select * from tbl_employee where id=#{id} and last_name=#{lastName}
</select> <!-- 查询方法(多个参数)
多个参数: mybatis 会做特殊处理
多个参数会被封装成一个 map,
其中 key: param1,...paramN, 或者参数的索引
value: 传入的参数值
#{}就是从 map 中获取指定的key值
-->
<select id="getEmpByIdAndLastName" resultType="cn.itcast.mybatis.bean.Employee">
select * from tbl_employee where id=#{param1} and last_name=#{param2}
</select> <!-- 查询方法(多个参数)
也可以使用命名参数的方法: 在封装参数时,明确指定map中的key值:
接口的写法:
public Employee getEmpByIdAndLastName(@Param("id")Integer id,
@Param("lastName")String lastName)
-->
<select id="getEmpByIdAndLastName" resultType="cn.itcast.mybatis.bean.Employee">
select * from tbl_employee where id=#{id} and last_name=#{lastName}
</select> <!-- 查询方法(多个参数)
POJO:
如果多个参数正好是业务逻辑的数据模型,可以直接传入POJO;
#{属性名}: 取出传入的POJO类的属性值 Map:
如果多个参数不是业务模型中的数据,没有对应的POJO,不经常使用, 为了方便,也可以传入Map
#{key}: 取出map中对应的值
此时, 接口中的方法:
public Employee getEmpByMap(Map<String, Object> map); TO:
如果多个参数不是业务模型的数据,但是经常要使用,推荐编写一个 TO(Tranfer Object)数据传输对象 特别注意: 如果是 Collection(List,Set)类型或者是数组,mybatis 也会特殊处理,把传入的list或
者数组封装到map中,
其中,key: Collection(collection), 如果是 List, 还可以使用 key(list),数组(array)
public Employee getEmpById(List<Integer> ids);
取出list集合中第一个id的值: #{list[0]}
-->
<select id="getEmpByMap" resultType="cn.itcast.mybatis.bean.Employee">
select * from tbl_employee where id = #{id} and last_name=#{lastName}
</select> </mapper> // 编写测试类
public class MyBatisTest{
// 1. 获取 SqlSessionFactory 方法(同上) // 2. 测试方法
@Test
public void test01() throws IOException{
// 1. 获取 SqlSessionFactory 对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2. 获取 SqlSession 实例
// sqlSessionFactory.openSession(); 该实例需要手动提交数据
// sqlSessionFactory.openSession(true); 该实例可以自动提交数据
SqlSession openSession = sqlSessionFactory.openSession(); try{
// 3. 获取接口的实现类对象
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); // 4. 查询数据
Map<String,Object> map = new HashMap<String,Object>();
map.put("id",1);
map.put("lastName","zhangsan");
Employee employee = mapper.getEmpByMap(map);
System.out.println(employee); }finally{
// 5. 关闭资源
openSession.close();
}
}
}

4.2 参数值的获取

  1. #{}: 可以获取map中的值或者pojo对象属性的值;
  2. ${}: 也可以获取map中的值或者pojo对象属性的值;
  3. 区别:
    • #{}: 是以预编译的形式,将参数设置到sql语句中, PreparedStatement: 可以防止 Sql 注入;
    • ${}: 取出的值直接拼装在sql语句中, 会有安全问题;
    • 大多情况下,应该使用 #{};

4.3 #{}更丰富的用法

  • 参数位置支持的属性: javaType, jdbcType, mode(存储过程), numericScale, resultMap, typeHandler,

    jdbcTypeName;
  • 实际上,通常被设置的是: 可能为空的列名指定 jdbcType;因为mybatis对所有null都映射的是原生Jdbc的 OTHER;

    Oracle 数据库不能正确识别,会报错;
  • #{email,jdbcType=NULL}表示email列为null时,该列的类型为原生Jdbc的 NULL类型;

参考资料

MyBatis 入门(一)的更多相关文章

  1. MyBatis1:MyBatis入门

    MyBatis是什么 MyBatis是什么,MyBatis的jar包中有它的官方文档,文档是这么描述MyBatis的: MyBatis is a first class persistence fra ...

  2. mybatis入门基础(二)----原始dao的开发和mapper代理开发

    承接上一篇 mybatis入门基础(一) 看过上一篇的朋友,肯定可以看出,里面的MybatisService中存在大量的重复代码,看起来不是很清楚,但第一次那样写,是为了解mybatis的执行步骤,先 ...

  3. MyBatis入门基础(一)

    一:对原生态JDBC问题的总结 新项目要使用mybatis作为持久层框架,由于本人之前一直使用的Hibernate,对mybatis的用法实在欠缺,最近几天计划把mybatis学习一哈,特将学习笔记记 ...

  4. MyBatis入门案例、增删改查

    一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...

  5. mybatis入门_mybatis基本原理以及入门程序

    一.传统jdbc存在的问题 1.创建数据库的连接存在大量的硬编码, 2.执行statement时存在硬编码. 3.频繁的开启和关闭数据库连接,会严重影响数据库的性能,浪费数据库的资源. 4.存在大量的 ...

  6. MyBatis入门学习教程-使用MyBatis对表执行CRUD操作

    上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...

  7. MyBatis入门学习(二)

    在MyBatis入门学习(一)中我们完成了对MyBatis简要的介绍以及简单的入门小项目测试,主要完成对一个用户信息的查询.这一节我们主要来简要的介绍MyBatis框架的增删改查操作,加深对该框架的了 ...

  8. MyBatis入门学习(一)

    一.MyBatis入门简要介绍(百科) MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyB ...

  9. MyBatis入门案例 增删改查

    一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...

  10. MyBatis入门(五)---延时加载、缓存

    一.创建数据库 1.1.建立数据库 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.7.9-log : Database - mybatis ****** ...

随机推荐

  1. Atitit.分区对索引的影响 分区索引和全局索引 attilax总结

    Atitit.分区对索引的影响 分区索引和全局索引 attilax总结 1. 分区的好处1 2. 分区键:2 3. 分区的建议:2 4. 分区索引和全局索引:2 5. 全局索引就是在全表上创建索引, ...

  2. 李洪强和你一起学习前端之(4)HTML5介绍

    1.1认识HTML5 html的版本: html4 Xhtml1.0 目前: html5是最高的版本 再怎么变化,无非是多了一些标签而已,但是不单单是提供了一些标签 比如: 开发网页游戏 我们可以开发 ...

  3. CCNA2.0笔记_VLSM

    子网化:把一个大的主类网段,通过借位的方式逻辑划分多个子网段,应用于多个广播域: 做子网划分的时候,子网掩码最多只能到30位,不能再多划(因为至少要保留4个地址,即2个主机位) FLSM(定长子网掩码 ...

  4. ORACLE 中 TRANSLATE的用法

    --TRANSLATE(string,from_str,to_str) --to_str和from_str中的字符一一对应 --如果string里有,from_str字符集里没有的字符,将保留 --如 ...

  5. hive执行更新和删除操作

    Hive从0.14版本开始支持事务和行级更新,但缺省是不支持的,需要一些附加的配置.要想支持行级insert.update.delete,需要配置Hive支持事务. 一.Hive具有ACID语义事务的 ...

  6. shell程序练习

    #!/bin/sh通知采用bash解释.如果在echo语句中执行shell命令date,则需要在date命令前面加符号&: 编辑完文件之后不能立即执行该文件,需要给文件设置可执行权限.chmo ...

  7. linux上FTP服务器搭建

    一.启动vsftpd服务 1. 启动VSFTP服务器 A. cenos下运行:yum install vsftpd B. 登录Linux主机后,运行命令:"service vsftpd st ...

  8. MapReduce实战(一)自定义类型

    需求: 处理以下流量数据,第1列是手机号,第7列是上行流量,第8列是下行流量.将手机号一样的用户进行合并,上行流量汇总,下行流量也汇总,并相加求得总流量. 1363157985066 13726230 ...

  9. wget命令 -c断点续传

    wget -O   wordpress.zip http://www.linuxde.net/download.aspx?id=1080 下载文件在指定位置并进行重命名 -O file       - ...

  10. 【BZOJ】3432: [Usaco2014 Jan]Cross Country Skiing (bfs+二分)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3432 题目说要相互可达,但是只需要从某个点做bfs然后判断其它点是否可达即可. 原因太简单了.... ...