Mybatis
Mybatis特点
属于持久层ORM框架
- 持久层: 讲内存中对象数据,转移到数据库中的过程持久层
Mybatis Hibernate Spring-jpa - ORM Object Relational Mapping 对象关系映射框架
类 表
属性 字段
对象 记录 - 半自化 自动化
Mybatis 半自动化
表需要手动进行设计
提供sql
依赖与数据库平台
优点:学习使用简单(基与原声jdbc封装),优化灵活,适合做互联网项目
Hibernate 自动化ORM框架
表可以通过框架自动创建
省略一些基本的sql
不依赖与数据库平台
缺点: 学生成本高,优化难度大,适合与传统框(OA|图书管理系统…),不适合 做大型互联网项目
Mybatis环境搭建
官网: https://mybatis.org/mybatis-3/zh/index.html
新建Java项目
新建Java项目,导入核心java包与mybatis依赖jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UaAT0er8-1627737209959)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627735671004.png)]
导入jar包
mybatis核心jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o0tUWRiM-1627737209961)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627735699696.png)]
mybatis依赖jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kturGbf2-1627737209962)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627735712858.png)]
数据库驱动jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J0o3fKZ3-1627737209964)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627735732459.png)]
Build Path
选中所有的jar包,右键build path->add to build path 管理外部的jar资源
Mybatis配置文件
mybatis提供两种配置文件,
- 核心配置文件 mybatis-config.xml|mybatis.xml
- SQL映射文件mapper.xml
核心配置文件添加
是一个xml文件,命名无要求,位置无要求,一般成为mybatis.xml,放在src路径下
mybatis.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">
<!-- mybatis的全局配置文件 -->
<configuration>
<!--
用于指明使用哪一个开发环境
default : 用于指定使用的环境的id属性值
-->
<environments default="ev">
<!-- 用户配置开发环境 id: 环境的唯一标识 -->
<environment id="ev">
<!--
事务管理器
JBDC : 表示采用JDBC一样的事务管理方式
-->
<transactionManager type="JDBC"/>
<!--
用于配置数据库连接吃和数据库连接参数
POOLED : 表示mybatis采用连接池技术
-->
<dataSource type="POOLED">
<property name="driver"
value="oracle.jdbc.driver.OracleDriver"/>
<property name="url"
value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="username" value="SCOTT"/>
<property name="password" value="TIGER"/>
</dataSource>
</environment>
</environments>
<!-- SQL映射文件配置 -->
<mappers>
<!-- 指明SQL映射文件路径 resource : 包路径 com/.../xxxMapper.xml-->
<mapper resource="com/xxxx/mappers/UserMapper.xml"/>
</mappers>
</configuration>
Mybatis SQL映射文件:
在Mybatis中,推荐使用mappers作为包名,我们只需要写一个映射配置文件就可以,UserMapper.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: 命名空间
-->
<mapper namespace="com.xxxx.mappers.UserMapper">
<!--
查询标签: select 用于编写查询语句
id : 当前文件中保证唯一
resultType : 结果的类型
parameterType : 入参类型
-->
<select id="queryAll" resultType="com.xxxx.pojo.User">
select * from t_user
</select>
</mapper>
注意:不要忘记mybatis核心xml文件中的mapper配置
测试
public class TestUser {
public static void main(String[] args) throws IOException {
//1.加载mybatis全局核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//2.构建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂获取会话SqlSession
SqlSession session = factory.openSession();
//4.通过session调用方法执行查询
//selectList() 查到的数据返回一个list集合,没查到返回空的list
//selectList 的第一个参数为statement: 命名空间+id
List<User> list =
session.selectList("com.xxxx.mappers.UserMapper.queryAll");
System.out.println(list);
//5.关闭会话资源
session.close();
}
}
Mybatis配置文件详解
核心配置文件
1.configuration
配置文件的根元素,所有其他的元素都要在这个标签下使用(dtd文件规定)
2.environments default=“environment”
用于管理所有环境, 并可以指定默认使用那个环境,通过defualt属性来指定
3.environment
用来配置环境,id属性用于唯一标识当前环境
4.transactionManager type=“JDBC”
用户配置事务管理器
type属性
用来指定Mybatis采用何种方式管理事务
JDBC : 表示采用与原生JDBC一致方式管理事务
MANAGED: 表示讲事务管理交给其他容器进行, Spring
5.dataSource type=“POOLED”
用于配置数据源, 设置Myabtis是否使用连接池技术,并且配置数据库的四个 连接参数
type属性:
POOLED : 表示采用连接池技术
UNPOOLED: 表示每次都会开启和关闭连接, 不采用连接池技术
JNDI : 使用其他容器提供数据源
6.property
用于配置数据库连接参数 (driver,url,username,password)
7.Mappers
用于配置扫描sql映射文件
SQL映射文件(mapper)
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就
显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代
码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语句
查询语句是 MyBatis 中最常用的元素之一(映射文件配置见代码)
1.mapper
SQL映射文件的根元素
namespace 属性
用于指定命名空间, mydatis通过namespace+id的方式用来定位sql语句,所以必须要指定
namespace,通过被配置为权限定路径 包名+xml文件名(不带后缀名)
2.select
用来定义查询语句 update insert delete
id 属性
用阿里唯一表示当前sql语句,在当前的命名空间中唯一,不能重复 , 类型方法名
resultType 属性
用于设定查询返回的结果的数据类型,要写类型的权限定名(包名+类名),如果返回值的是集合类型,要定义集合的泛型类型
三个查询方法
- selectList(“命名空间.id”) 用户查询多条数据情况,返回一个List集合, 没有查到数据返回空集合,不是null
- selectOne(“命名空间.id”) 用于查询单条数据,返回一个数据, 如果没有查到返回null
- selectMap(“命名空间.id”,key的字段名) 用于查询多条记录情况, 返回Map集合, 需要指定那个属性作为key, sql查询结果作为value,指定的字段值作为key, 如果查不到, 返回一个空map集合,不是null
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
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 com.xxxx.pojo.User;
public class UserTest {
public static void main(String[] args) throws IOException {
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//2.获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//3.获取会话
SqlSession session = factory.openSession();
//4.操作
//1)selectList("namespace.id") 用于查询多条数据,返回一个list集合,如果没有查询到
任数据,返回空集合,不是null
List<User> list =
session.selectList("com.xxxx.mappers.UserMapper.queryAll");
System.out.println(list);
//2)selectOne("namespace.id")
User user = session.selectOne("com.xxxx.mappers.UserMapper.queryById");
System.out.println(user);
//3)selectMap("namespace.id","执行作为key的属性")
Map<Integer,User> map =
session.selectMap("com.xxxx.mappers.UserMapper.queryAll", "id");
System.out.println(map);
//5.关闭session
session.close();
}
}
typeAliases标签
用于给java类型定义别名,方便在配置文件中使用
使用方式
给User类定义别名为u
<typeAliases>
<typeAlias type="com.xxxx.pojo.User" alias="u"/>
</typeAliases>
省略alias属性, 表示类别名为类名, 大小写不敏感
<typeAliases>
<typeAlias type="com.xxxx.pojo.User"/> alias属性不写,默认类名,不区分大小写
</typeAliases>
可以通过package标签给整个包下的所有类定义别名,别名为类名
<typeAliases>
<package name="com.xxxx.pojo"/> <!-- 包下所有的类默认类名 -->
</typeAliases>
<select id="queryAll" resultType="u">
select id,uname,upwd,birthday from t_user
</select>
<select id="queryById" resultType="User">
select id,uname,upwd,birthday from t_user where id=125
</select>
parameterType入参类型
parameterType: 基本数据类型(四类八种) 包装类 String Date Javabean Map List 数组 …
基本数据类型|包装类
<!-- 入参类型: 基本数据类型int|Integer -->
<!-- 根据用户id查询用户信息 -->
<select id="queryById" resultType="string" parameterType="int">
</select>
/* 参数基本数据类型 int->Integer
* 根据id查询用户名 第二个参数为sql传递的参数
*/
String name=session.selectOne("com.xxxx.mapper.UserMapper.queryById", 126);
System.out.println(name);
String
<!-- 入参类型 : String 根据用户名查询用户信息-->
<select id="queryUserByName" parameterType="String" resultType="User">
select <include refid="user_all_field"/> from t_user where uname = #{0}
</select>
//测试参数类型: String
List<User> list=session.selectList("com.xxxx.mapper.UserMapper.queryUserByName",
"zhangsan");
list.forEach(System.out::println);
JavaBean
<!-- 入参类型: Javabean -->
<select id="queryUserByNamePwd" parameterType="user" resultType="User">
<!-- 如果参数为对象,可以通过#{对象的属性名}匹配不同的属性值 -->
select <include refid="user_all_field"/> from t_user where uname =#{uname}
and upwd = #{upwd}
</select>
/*
* 参数为Javabean User对象
* 根据用户名和密码查询用户信息
*/
User user = new User("zhaoliu","4567");
List list=session.selectList("com.xxxx.mapper.UserMapper.queryUserByNamePwd",
user);
System.out.println(list);
Map
<!-- 入参类型: Map 根据多个id,查询用户信息-->
<select id="queryUserByIdMap" parameterType="map" resultType="user">
select <include refid="user_all_field"/> from t_user where id = #{id1} or
id=#{id2}
</select>
数组|List
<!-- 参数为数组 根据多个用户名查询用户信息-->
<select id="queryByArray" resultType="User">
select <include refid="user_all_field"/> from t_user where uname in(
<!--
foreach 遍历参数
collection="array" array遍历数组参数 list集合
item : 每次遍历获取的数据值
separator : 分隔符(每次遍历的数据使用分隔符进行连接)
-->
<foreach collection="array" item ="item" separator=",">
#{item}
</foreach>
)
</select>
//Array
String[] arr={"hahaha","zhangsan","lisi"};
List<User> list=session.selectList("com.xxxx.mapper.UserMapper.queryByArray",
arr);
list.forEach(System.out::println);
工具类的封装
package com.xxxx.utils;
import java.io.IOException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtils {
private static SqlSessionFactory factory = null;
static {
try {
factory = new
SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* 返回一个会话
*/
public static SqlSession getSession() {
SqlSession session =null;
if(factory!=null) {
//session = factory.openSession(); //默认手动提交事务
session = factory.openSession(true); //自动提交
}
return session;
}
}
接口绑定方案
Myabtis中,提供了一套接口绑定方案,程序员可以提供一个接口,然后提供一个与接口所对应的mapper.xml文件
Myabaits会自动讲接口与xml文件进行绑定,实际上就是Mybatis互根据接口和对应的xml文件创建一个接口的实现类,换言之,就是可以得到接口类型的一个对象,方便方法的调用
定义接口
/*
* 接口 定义了对用户的操作
*/
public interface UserMapper {
//查询所有用户
public List<User> queryAll();
}
映射文件
注意:
- xml文件名要与接口名保持一致
- namespace属性值 必须与接口的权限定名
- id属性必须与抽象方法名保持一致
- 返回值类型和参数类型与方法的返回值和参数保持一致
<?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 ="com.xxxx.mapper.UserMapper">
<!-- id 与 方法名一致 -->
<select id="queryAll" resultType="User">
select * from t_user
</select>
</mapper>s
在核心配置文件中扫描接口
- 扫描单个接口,可以使用mapper标签的class属性
<!-- mapper 配置扫描接口 -->
<mappers>
<mapper class="com.xxxx.mapper.UserMapper"/> <!--配置某个接口 -->
</mappers>
- 扫描多个接口,可以简化配置,使用package标签,表示扫描对应包下的所有接口
<!-- mapper 配置扫描接口 -->
<mappers>
<package name="com.xxxx.mapper"/>
</mappers>
使用
在使用时,通过SqlSession的getMapper() 方法,返回接口代理对象,从而调用以实现的抽象方法
/*
* 测试接口绑定
*/
@Test
public void test(){
SqlSession session = MybatisUtils.getSession();
//getMapper()获取接口实现类对象,参数为接口的class对象,通过参数指定接口
UserMapper mapper =session.getMapper(UserMapper.class);
//通过对象调用方法
List<User> list = mapper.queryAll();
System.out.println(list);
session.close();
}
通过接口绑定解决多参数传递问题
方式一
a)接口中定义方法
User selByUP(String username, String password);
b) 映射文件中提供对应的标签. 此时, SQL 语句中获取方式有两种, 通过#{arg+数字}或#{param+数字}的
方式.
<select id="selByUP" resultType="user">
select * from t_user where username=#{param1} and password=#{param2}
</select>
方式二
a) 接口中定义方法, 参数中使用@Param 注解设定参数名用于在 SQL 语句中使用.
User selByUP(@Param("username") String username, @Param("password")
String password);
b) 映射文件中提供对应的标签. 此时, SQL 语句中获取方式有两种, 通过#{参数名称}或#{param+数字}的
方式
<select id="selByUP" resultType="user">
select * from t_user where username=#{username} and
password=#{password}
</select>