一.Mybaits的简单入门
1 MyBatis框架由来
(1)框架简介
框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们个性化的需求!
框架:大工具,我们利用工具,可以快速开发项目 (mybatis也是一个jar包,不过提供的功能更加多)
jar包:小工具
- 生活中的例子,比如盖房子
- 张三想盖红色的房子,他需要先给架构搭起来,然后再给房子图上红色
- 李四想盖蓝色的房子,他也需要先给架构搭起来,然后再给房子图上蓝色
- 比如很多人都需要盖房子,那么肯定会有很多重复性的工作,比如说基础架构
- 这时候就有公司出了一个解决方案,准备好了房子的架构(上图左下角黑色的),谁需要盖房子,只需要借助于公司提供的架构,在这个基础之上进行装修,涂色即可
(2)ORM介绍
ORM(Object Relational Mapping): 对象关系映射
- object:指的是实体对象,javabean
- relational:指的是关系型数据库,比如mysql
- Mapping: 映射,一 一对应的关系
指的是持久化数据和实体对象的映射模式,为了解决面向对象与关系型数据库存在的互不匹配的现象的技术。
简单说,ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写
ORM 把数据库映射成对象,具体映射关系如下图:
说白了:就是Student类对应Student表。Student类中的类属性,对应数据库中的表字段....
(3)原始的jdbc操作分析
public class JDBCDemo01 {
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "123456");
// 3.获取执行者对象
Statement stat = con.createStatement();
// 4.执行sql 语句,并且接收结果
String sql = "SELECT * FROM student";
ResultSet rs = stat.executeQuery(sql); //execute 执行 query 查询
// 5.处理结果
while (rs.next()){
System.out.println(rs.getInt("id") +"\t" + rs.getString("name"));
}
rs.close();
stat.close();
con.close();
}
}
原始 JDBC 的操作问题分析
1. 频繁创建和销毁数据库的连接会造成系统资源浪费从而影响系统性能
2.sql 语句在代码中硬编码,如果要修改 sql 语句,就需要修改 java 代码,造成代码不易维护
3.查询操作时,需要手动将结果集中的数据封装到实体对象中
4.增删改查操作需要参数时,需要手动将实体对象的数据设置到 sql 语句的占位符
原始 JDBC 的操作问题解决方案
1. 使用数据库连接池初始化连接资源
2.将 sql 语句抽取到配置文件中
3.使用反射、内省等底层技术,将实体与表进行属性与字段的自动映射
4.通过分析原始jdbc操作存在的问题,以及对应的解决方案,那么在对应的解决方案在完全可以使用MyBatis替代
(4)什么是MyBatis
- mybatis 是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程
- mybatis通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句
- 最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作
- MyBatis官网地址:MyBatis中文网
2.Mybatis的快速入门
(1)步骤:
- 数据准备(包括数据库内的学生表数据和Student类)
- 导入jar包(数据库连接jar包 和mybatis的jar包)
- 在src下创建映射配置文件
- 在src下创建核心配置文件
- 编写测试类完成相关API使用
(2)结构层级
(3)代码演示:
MyBatisConfig.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="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://localhost/db26?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="8Gd_GFI=*jo&"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/bukaedu/StudentMapper.xml"/>
</mappers>
</configuration>
StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--名称空间-->
<mapper namespace="StudentMapper">
<select id="selectAll" resultType="com.bukaedu.Student">
select * from student
</select>
</mapper>
Student类 --对应Student表中数据(ORM)
public class Student {
Integer id;
String name;
Integer age;
public Student(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer 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;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
Test类
public class Test {
public static void main(String[] args) throws Exception {
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("com/bukaedu/MyBaitsConfig.xml");
/*
咱们也可以写成这样:
InputStream is = Test.class.getClassLoader(). getResourceAsStream("com/bukaedu/MyBaitsConfig.xml");
通过类加载器的形式获取这个核心配置文件,而我们有个Resource这个API就更好了
*/
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.执行映射配置文件的sql语句,并接收结果。
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");//字符串内写(名称空间+id标识)就能找到要用的SQL语句。
//5.处理结果
for(Student s :list){
System.out.println(s);
}
}
}
3 Mybaits相关的API
(1) Resources
来自org.apache.ibatis.io.Resoureces:加载资源的工具类
(2)SqlSessionFactoryBuilder
来自org.apache.ibatis.io.SqlSessionFactoryBuilder:获取SqlSessionFactory工厂对象的功能类
(3)SqlSessionFactory
来自org.apache.ibatis.session.SqlSessionFactory:获取SqlSession构建者对象的工厂接口
(4)SqlSession
来自org.apache.ibatis.session.SqlSession:构建者对象接口。用于执行SQL,管理事务,接口代理。
4.Mybatis映射配置文件(Mapper.xml)
- 映射配置文件包含了数据和对象之间的映射关系以及要执行的SQL语句
5.Mybatis核心配置文件(Mybaits.xml)
PS:根据我们的开发规范要求数据库的连接信息单独的保存在一个类中,这样我们有以下的方法。
(1)<properties>:引入数据库连接配置文件标签
(2)属性:
resource:数据库连接配置路径
(3)获取数据库连接参数:$(键名)
(2)起别名
(1)<typeAliases>:为全类名起别名的父标签
(2)<typeAlias>:为全类名起别名的子标签
(3)属性:
type:指定全类名
alias:指定别名
(4)<package>:为指定包下所有类起别名的子标签。(别名就是类名)
Mybaits常见数据类型别名:
6 MyBaits传统开发
分层思想:控制层(controller)、业务层(service)、持久层(dao)。
调用流程:
PS:在mybatis项目中持久层就不再叫dao了,而是叫做mapper(其实都是一样的,就是换个名字)
7 log4j
(1) 在日常开发过程中,排查问题时难免需要输出 MyBatis 真正执行的 SQL 语句、参数、结果等信息,我们就可以借助 LOG4J 的功能来实现执行信息的输出。
(2)使用步骤:
- 导入lo4j的jar包
- 修改核心配置文件.(增加log4j配置信息)
<!--配置LOG4J:以下name和value是固定写法-->
<settings>
<setting name="logImpl" value="log4j"/>
</settings>
configuration下的节点顺序是有要求的,settings必须是在properties下,放在其他位置会报错。
3.在src下编写log4j配置文件(命名为log4j.properties)
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
(3)添加log4j后的打印输出
二 MyBaits进阶
1.Mapper接口代理方式实现Dao层
★实现规则:
- 映射配置文件中的名称空间必须和Dao层接口的全类名相同
- 映射配置文件中的增删改查标签的id属性必须和Dao层接口的方法名相同
- 映射配置文件中的增删改查标签的parameterType属性必须和Dao层接口方法的参数相同
- 映射配置文件中的增删改查标签的resultType属性必须和Dao层接口方法的返回值相同
Student类
public class Student {
Integer id;
String name;
String age;
public Student(Integer id, String name, String age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
StudentMapper接口
public interface StudentMapper{
List<Student> selectAll();
Student selectOne(Integer id);
int insert(Student student);
int update(Student student);
int delete(Integer id);
}
采用单元测试的方法进行运行
public class Demo {
//查询全部
@Test
public void SelectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("com/bukaedu/MyBaitsConfig.xml");
//2.获取sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> list = mapper.selectAll();
for(Student s :list){
System.out.println(s);
}
is.close();
sqlSession.close();
}
//单个查询
@Test
public void SelectOne()throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("com/bukaedu/MyBaitsConfig.xml");
//2.获取sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectOne(2);
System.out.println(student);
is.close();
sqlSession.close();
}
//添加数据
@Test
public void insert() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("com/bukaedu/MyBaitsConfig.xml");
//2.获取sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student stu =new Student(6,"刘六","29");
int insert = mapper.insert(stu);
System.out.println(insert);
is.close();
sqlSession.close();
}
//修改数据
@Test
public void update() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("com/bukaedu/MyBaitsConfig.xml");
//2.获取sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student stu =new Student(6,"刘六","88");
int update = mapper.update(stu);
System.out.println(update);
is.close();
sqlSession.close();
}
//删除数据
@Test
public void delete() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("com/bukaedu/MyBaitsConfig.xml");
//2.获取sqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
int delete = mapper.delete(6);
System.out.println(delete);
is.close();
sqlSession.close();
}
}
三 MyBaits映射配置文件----动态SQL
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。
<where>:条件标签。如果有动态条件,则使用该标签代替 where 关键字。
<if>:条件判断标签。
语法:
<if test=“条件判断”>
查询条件拼接
</if>
(1)利用动态SQL之if去解决它
(2)动态SQL--foreach
<foreach>:循环遍历标签。适用于多个参数或者的关系。
语法:
<foreach collection="" open="" item="" separator="">
获取参数
</foreach>
属性:
collection:参数容器类型,(list-集合,array-数组)
open:开始的SQL语句
close:结束的SQL语句
item:参数变量名
separator:分隔符
(3)动态SQL---SQL片段的抽取
SQL片段抽取:
我们可以将一些重复性的SQL语句进行抽取,以达到的复用的效果
语法:
<sql>:抽取sql语句标签
<sql id=”片段的唯一标识“>抽取的SQL语句</sql>
<include>:引入SQL片段标签:
<include refid="片段唯一标识"/>