Mybatis入门学习笔记(一)
1. 绪论
1.1 框架
- 三层架构:
-
表述层 servlet
-
业务逻辑层 javabean
-
数据持久层 JDBC
大量时间用于搭建项目。开发效率比较低。其实对于开发人员来说,重要的是业务,更应该关注业务。
- 实际上,框架就是将重复繁琐的代码实现封装,让开发人员将更多的精力放在业务的理解和分析上。
- 框架的意义:提高开发效率、隐藏细节
1.2 三大框架 SSH->SSM
- 表述层:用户交互 servlet------SpringMVC/struts2
- 业务逻辑层: 业务处理 javabean/ejb----Spring
- 数据持久层: 数据库 JDBC----Mybatis/Hibernate
1.3 传统JDBC
-
连接数据库时四个关键参数的使用有硬编码。即用户名、密码、数据库地址、数据库驱动被写死,怎么解决?使用xml文件配置
-
statement使用中存在硬编码。
-
频繁的建立和关闭连接。(数据源、连接池)
1.4 Mybatis
传统框架的不足,使得Mybatis框架应运而生。
-
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
在框架里面写代码不多,但需要大量配置。
-
MyBatis 是一个优秀的ORM框架。
ORM:Object Relationship Mapping(对象关系映射)
将对象通过一定的方式插入数据库。
-
Mybatis不需要开发人员更多的关注数据库的连接和关闭以继statement对象的创建,着重关注SQL语句。
即:关注映射,输入参数和输出参数。
Mybatis更像一个黑匣子。
2. Mybatis开发
2.1 Mybatis下载与安装
- Mybatis的前身是ibatis,后期这个项目被移植到Google code才正式更名为Mybatis。
github中可以下载Mybatis。 - 要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath 中即可。
- 如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
2.2 Mybatis使用须知
- 配置文件
- xfg.xml 核心配置文件(全局配置文件):连接信息的配置(连接池)、事务管理
- mapper.xml 映射文件
- SqlsessionFactory: session工厂
- Sqlsession :面向程序员的接口(增删改查)
2.3 搭建步骤
- 创建一个maven项目,引入相关的依赖。
- 常用Mybatis的依赖jar包
-
配置核心配置文件(xml)
注意:此处配置的并不是pom.xml文件哈~此处取名为MybatisDemo.xml
XML 配置文件中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。
<!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="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
environment 元素体中包含了事务管理和连接池的配置。mappers 元素则是包含一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。
传统的JDBC需要频繁建立和释放连接。使用连接池后,java向连接池申请连接,用完后归还至连接池即可。
连接池:
- 当项目启动,向数据库请求N条(N=初始化连接数)连接放置在连接池中管理。
- 当连接的请求多于初始化连接数,此时会根据步长来增加连接数(创建连接)。增加的连接数最大不超过最大连接数,仍不够时需要根据超时时间进行等待。
- 当连接的请求远低于当前的连接数,此时会根据最小连接数释放相应的连接。
- 减少连接的频繁关闭,但连接需要占用资源。
- 常用连接池: DBCP C3P0 DROID
2.4 小结
- 项目结构
- pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mybatis</groupId>
<artifactId>MybatisDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
</dependencies>
</project>
- DataMapper.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">
<!-- 描述对象和记录之间的映射关系
namespace :隔离sql,在mapper代理时有特殊用法-->
<mapper namespace="com">
<!-- 查询的映射 (Statement对象)
id:唯一标识
#{}: 代表占位符
parameterType:输入参数类型(输入参数的映射)(可省略)-->
<select id="selectData" resultType="entity.Data" parameterType="int">
select * from yangtingting where id = #{id}
</select>
</mapper>
4. MybatisDemo.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>
<!-- 环境 environments 复数 环境集合(MYSQL/Oracle)
default:默认(环境的id)
-->
<environments default="development">
<!--environments:代表一个环境
id:唯一标识
transactionManager:事务管理器
dataSource:数据源(连接池),必须配置四个参数-->
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ytt?3useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<!-- 映射器-->
<mappers>
<mapper resource="DataMapper.xml"/>
</mappers>
</configuration>
- Data.java
package entity;
public class Data {
private int id;
private String name;
private int age;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
- Test.java
import entity.Data;
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.InputStream;
public class Test {
public static void main(String[] args) throws Exception{
//加载配置文件为流
InputStream is=Resources.getResourceAsStream("MybatisDemo.xml");
//创建SqlSessionFactory工厂
SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(is);
//核心接口(发送SQL语句)
SqlSession session=ssf.openSession();
Data data=session.selectOne("com.selectData",2);
System.out.println("ID:"+data.getId()+"\n"+"姓名:"+data.getName()+"\n"+"年龄:"+data.getAge());
//释放资源
session.close();
}
}
- Mysql数据库
8. 运行结果
至此,一个简单的Mybatis的入门项目就已经完成了。
3. 配置详解
3.1 核心配置文件
- 属性(properties)------可外部配置且可动态替换
- 可以在典型的 Java 属性文件中配置,即java的属性文件外部引入 resource=“jdbc.properties”
- 亦可通过 properties 元素的子元素来传递,property标签中配置
- 当两者冲突时,最终使用Java的属性文件的配置
-
设置(settings)–这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
-
类型别名(typeAliases)
类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
-
类型处理器(typeHandlers)
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
-
对象工厂(objectFactory)
MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。
ObjectFactory 接口很简单,它包含两个创建用的方法,一个是处理默认构造方法的,另外一个是处理带参数的构造方法的。 最后,setProperties 方法可以被用来配置 ObjectFactory,在初始化你的 ObjectFactory 实例后, objectFactory 元素体中定义的属性会被传递给 setProperties 方法。
-
插件(plugins)
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。
-
环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中 使用相同的 SQL 映射。有许多类似的使用场景。
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
-
事务管理器:
JDBC:和JDBC使用同样的提交和回滚策略
MANAGED:依赖于应用服务器上下文(context)的配置(必须在服务器上运行)
-
数据源
UNPOOLED:请求时连接,完毕时关闭
POOLED:连接池
JNDI:依赖于应用服务器,即在上下文配置数据源,然后再java获取上下文的引用从而获取数据源
- 映射器(mappers):引用已经配置好的配置文件
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。 但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。
3.2 映射文件–与业务相关
4. 基本查询操作
4.1 概念
- 查询映射:
<select id="selectData" resultType="entity.Data" parameterType="int">
select * from yangtingting where id = #{id}
</select>
-
id:唯一标识
-
#{}: 代表占位符
-
parameterType:输入参数类型(输入参数的映射)(可省略)
-
输入参数的映射:
简单类型:int,string 可以随意写
对象类型:#{}值为属性名称
map:#{}值为key值
包装类:属性导航 -
resultType:结果类型 (输出结果的映射)(可省略)
简单类型:int,string 可以随意写
对象类型:字段与属性之间一一对应
注意:字段名称,即结果集中的名字和属性名称必须一致 -
resultMap:写外部resultMap的id
4.2 根据id查询
映射文件----DataMapper.xml
<select id="selectData" resultType="entity.Data" parameterType="int">
select * from yangtingting where id = #{id}
</select>
Test.java
ata data=session.selectOne("com.selectData",2);
System.out.println("ID:"+data.getId()+"\n"+"姓名:"+data.getName()+"\n"+"年龄:"+data.getAge());
运行结果:
4.3 查询所有
映射文件----DataMapper.xml
<select id="selectAll" resultType="entity.Data" >
select * from yangtingting
</select>
Test.java
//查询所有
List<Data> list = session.selectList("com.selectAll");
for(int i = 0; i < list.size(); i++){
System.out.println(list.get(i).toString());
}
注意:一定要在Data.java中重写toString方法!!!
@Override
public String toString() {
return "Data{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
运行结果:
4.4 模糊查询
映射文件----DataMapper.xml
<select id="selectLike" resultType="entity.Data" >
select * from yangtingting where name like '%${value}%'
</select>
Test.java
//模糊查询
List<Data> list1 = session.selectList("com.selectLike","t");
System.out.println(list1);
模糊查询:有SQL注入的风险
4.5 分页查询
- 编写类
- map
<select id="selectPage" resultType="entity.Data" parameterType="map">
select * from yangtingting limit #{start},#{length}
</select>
//分页查询
Map map=new HashMap<>();
map.put("start",0);
map.put("length",2);
List<Data> list2 = session.selectList("com.selectPage",map);
System.out.println(list2);
- Mybatis RowBounds
<select id="selectPage1" resultType="entity.Data" parameterType="map">
select * from yangtingting
</select>
//分页查询
RowBounds bunds=new RowBounds(0,1);
List<Data> list3= session.selectList("com.selectPage1",null,bunds);
System.out.println(list3);
5. 增删改
5.1 增加数据
- 简单增加数据
映射文件----DataMapper.xml
<insert id="insertData" parameterType="entity.Data">
<!--useGeneratedKeys="true" keyProperty="id"-->
insert into yangtingting(name,age) values(#{name},#{age})
</insert>
Test.java
Data data1 = new Data("杨婷婷",24);
int rows=session.insert("com.insertData", data1);
session.commit();
System.out.println(rows);
注意:应该在Data.java中增加构造方法
public Data(String name, int age) {
this.name = name;
this.age = age;
}
- 插入,主键返回,用于建立多表之间的关系
<insert id="insertData" parameterType="entity.Data" useGeneratedKeys="true" keyProperty="id">
insert into yangtingting(name,age) values(#{name},#{age})
</insert>
Data data1 = new Data("杨婷婷",24);
int rows=session.insert("com.insertData", data1);
session.commit();
System.out.println(rows);
System.out.println(data1.getId());
5.2 删除数据
<delete id="deleteAuthor">
delete from Author where id = #{id}
</delete>
5.3 修改数据
<update id="updateAuthor">
update Author set
username = #{username},
password = #{password},
email = #{email},
bio = #{bio}
where id = #{id}
</update>
Data data1 = new Data();
data1.setId(2);
data1.setAge(24);
data1.setName("tyyyy");
session.insert("com.updateData", data1);
session.commit();
session.close();