框架是一款半成品软件,咱们能够基于这个半成品软件继续开发,来完成咱们个性化的需求!java
框架:大工具,咱们利用工具,能够快速开发项目 (mybatis也是一个jar包,不过提供的功能更加多)mysql
jar包:小工具sql
如图:数据库
生活中的例子,好比盖房子apache
张三想盖红色的房子,他须要先给架构搭起来,而后再给房子图上红色api
李四想盖蓝色的房子,他也须要先给架构搭起来,而后再给房子图上蓝色session
好比不少人都须要盖房子,那么确定会有不少重复性的工做,好比说基础架构mybatis
这时候就有公司出了一个解决方案,准备好了房子的架构(上图左下角黑色的),谁须要盖房子,只须要借助于公司提供的架构,在这个基础之上进行装修,涂色便可架构
ORM(Object Relational Mapping): 对象关系映射app
object:指的是实体对象,javabean
relational:指的是关系型数据库,好比mysql
Mapping: 映射,一 一对应的关系
指的是持久化数据和实体对象的映射模式,为了解决面向对象与关系型数据库存在的互不匹配的现象的技术。
如图:
简单说,ORM 就是经过实例对象的语法,完成关系型数据库的操做的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写
ORM 把数据库映射成对象,具体映射关系以下图:
原始 JDBC 的操做问题分析
1. 频繁建立和销毁数据库的链接会形成系统资源浪费从而影响系统性能
sql 语句在代码中硬编码,若是要修改 sql 语句,就须要修改 java 代码,形成代码不易维护
查询操做时,须要手动将结果集中的数据封装到实体对象中
增删改查操做须要参数时,须要手动将实体对象的数据设置到 sql 语句的占位符
原始 JDBC 的操做问题解决方案
1. 使用数据库链接池初始化链接资源
将 sql 语句抽取到配置文件中
使用反射、内省等底层技术,将实体与表进行属性与字段的自动映射
经过分析原始jdbc操做存在的问题,以及对应的解决方案,那么在对应的解决方案在彻底可使用MyBatis替代
mybatis 是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只须要关注sql语句自己,而不须要花费精力去处理加载驱动、建立链接、建立statement等繁杂的过程
mybatis经过xml或注解的方式将要执行的各类 statement配置起来,并经过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句
最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使咱们不用与jdbc api 打交道,就能够完成对数据库的持久化操做
MyBatis官网地址:http://www.mybatis.org/mybatis-3/
MyBatis开发步骤:
①添加MyBatis的jar包
②建立Student数据表
③编写Student实体类
④编写映射文件StudentMapper.xml
⑤编写核心文件MyBatisConfig.xml
⑥编写测试类
0) 新建java项目:mybatis01
1) 导入MyBatis的jar包 (在”今日资料\jar包“ 中,将jar包导入项目libs下)
mysql-connector-java-5.1.37-bin.jar
mybatis-3.5.3.jar
log4j-1.2.17.jar
2) 建立student数据表
3) 编写Student实体
package com.itheima.bean;
public class Student {
private Integer id;
private String name;
private Integer age;
//省略get个set方法
}
4) 新建测试类
package com.itheima.dao;
public class StudentTest01 {
/*
查询所有
*/
5) 编写src/StudentMapper.xml映射文件
6) 编写MyBatis核心文件: src/MyBatisConfig.xml
框架
框架是一款半成品软件,咱们能够基于框架继续开发,从而完成一些个性化的需求。
ORM
对象关系映射,数据和实体对象的映射。
MyBatis
是一个优秀的基于 Java 的持久层框架,它内部封装了 JDBC。
org.apache.ibatis.io.Resources:加载资源的工具类
mybatis的前身就是ibatis
核心方法
若是不使用Resources,那咱们能够本身使用类加载器(可是麻烦)
//InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
InputStream is = StudentTest01.class.getClassLoader().getResourceAsStream("MyBatisConfig.xml");
org.apache.ibatis.session.SqlSessionFactoryBuilder:获取 SqlSessionFactory 工厂对象的功能类
核心方法
经过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory fact ory = builder.build(inputStream);
org.apache.ibatis.session.SqlSessionFactory:获取 SqlSession 构建者对象的工厂接口。
核心api
代码
//3.经过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.执行映射配置文件中的sql语句,并接收结果
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");
说明:由于咱们的代码是执行了一个查询的语句,因此不用处理事务
org.apache.ibatis.session.SqlSession:构建者对象接口。用于执行 SQL、管理事务、接口代理。
核心api
SqlSession 实例在 MyBatis 中是很是强大的一个类。在这里你会看到全部执行语句、提交或回滚事务和获取映射器实例的方法
做用:
经过SqlSession对象,主要用途执行sql语句,对数据库进行操做
本质:
SqlSession 能够理解为至关于一个数据库链接(Connection 对象),你能够在一个事务里面执行多条 SQL,而后经过它的 commit、rollback 等方法,提交或者回滚事务
因此它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条链接,让它归还给SqlSessionFactory,不然数据库资源就很快被耗费精光,系统就会瘫痪,因此用 try...catch...finally... 语句来保证其正确关闭
Resources
加载资源的工具类
SqlSessionFactoryBuilder
获取 SqlSessionFactory 工厂对象的功能类
SqlSessionFactory
获取 SqlSession 构建者对象的工厂接口
指定事务的提交方式
SqlSession
构建者对象接口
执行 SQL
管理事务
接口代理
映射配置文件包含了数据和对象之间的映射关系以及要执行的 SQL 语句
这个namespace,命名空间,至关因而给这个映射节点,起一个名字
内部的全部增删改查的配置,都须要经过这个命名空间获取
语法:命名空间.id
<select>
:查询功能标签
属性
id:惟一标识, 配合名称空间使用。
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
SQL 获取参数: #{属性名}
修改StudentMapper.xml,增长以下:
由于参数类型是Integer,因此属性名能够更名字(#{sid})
可是这里的属性名通常是与数据库列名一致的
为啥叫属性名,其实应该是参数名,可是这个参数名通常都是与javabean中的属性名保持一致的,因此叫属性名
测试类StudentTest01.java,新增代码:
/*
根据id查询
*/
####3.3 新增功能
<insert>
:新增功能标签
属性
id:惟一标识, 配合名称空间使用
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
SQL 获取参数: #{属性名} #{列名}
修改StudentMapper.xml,增长以下:
注意:由于这里的参数类型是Student,因此属性名必须与Student的字段保持一致
测试类StudentTest01.java,新增代码:
/*
新增功能
*/
<update>
:修改功能标签
属性
id:惟一标识, 配合名称空间使用
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
SQL 获取参数: #{属性名}
修改StudentMapper.xml,增长以下:
注意:由于这里的参数类型是Student,因此属性名必须与Student的字段保持一致
测试类StudentTest01.java,新增代码:
/*
修改功能
*/
<delete>
:查询功能标签。
属性
id:惟一标识, 配合名称空间使用。
parameterType:指定参数映射的对象类型。
resultType:指定结果映射的对象类型。
SQL 获取参数: #{属性名}
修改StudentMapper.xml,增长以下:
测试类StudentTest01.java,新增代码:
/*
删除功能
*/
@Test
public void delete() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.经过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
int result = sqlSession.delete("StudentMapper.delete",5);
//5.提交事务
sqlSession.commit();
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
总结: 你们能够发现crud操做,除了标签名称以及sql语句不同以外,其余属性参数基本一致。
核心配置文件包含了 MyBatis 最核心的设置和属性信息。如数据库的链接、事务、链接池信息等。
以下图:
properties标签做用:
引入外部的数据库配置文件
标签属性
resource:数据库链接配置文件路径
获取数据库链接参数的语法格式
${键名}
优势
便于灵活的修改数据库链接池配置参数.
建立:src/jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.59.143:3306/db1
username=rooot
password=itheima
修改MyBatisConfig.xml配置文件:properties标签引入外部文件
<!--引入数据库链接的配置文件-->
<properties resource="jdbc.properties"/>
<!-- property获取数据库链接的配置信息 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<typeAliases>
:为全类名起别名的父标签。
<typeAlias>
:为全类名起别名的子标签。
属性
type:指定全类名
alias:指定别名 ([ˈeɪliəs]:别名)
<package>
:为指定包下全部类起别名的子标签。(别名就是类名)
以下图:
具体以下配置:修改MyBatisConfig.xml,增长代码以下:
<!--起别名-->
<typeAliases>
<typeAlias type="com.itheima.bean.Student" alias="student"/>
<!--<package name="com.itheima.bean"/>
若是bean包下有不少Javabean都须要起别名,就可使用package,指定一个包名
这样的话,就自动给这个包下全部的类添加别名,别名是类名的小写名字
-->
</typeAliase>
</typeAliases>
而后使用的时候就方便了,修改StudentMapper.xml中的com.itheima.bean.Student
<select id="selectAll" resultType="student"> SELECT * FROM student </select> <select id="selectById" resultType="student" parameterType="int"> SELECT * FROM student WHERE id = #{id} </select> <insert id="insert" parameterType="student"> INSERT INTO student VALUES (#{id},#{name},#{age}) </insert> <update id="update" parameterType="student"> UPDATE student SET name = #{name},age = #{age} WHERE id = #{id} </update> <delete id="delete" parameterType="int"> DELETE FROM student WHERE id = #{id} </delete>
分层思想:控制层(controller)、业务层(service)、持久层(dao)。
调用流程
实现步骤
在controller包下: 新建StudentContoller类
在service包下: 新建StudentService接口以及StudentServiceImpl实现类
在mapper包下:新建StudentMapper接口以及StudentMapperImpl实现类
StudentContoller----->StudentService----->StudentMapper
在mybatis项目中持久层就再也不叫dao了,而是叫作mapper(其实都是同样的,就是换个名字)
StudentMapper接口
package com.itheima.mapper; import com.itheima.bean.Student; import java.util.List; /* 持久层接口 */ public interface StudentMapper { //查询所有 public abstract List<Student> selectAll(); //根据id查询 public abstract Student selectById(Integer id); //新增数据 public abstract Integer insert(Student stu); //修改数据 public abstract Integer update(Student stu); //删除数据 public abstract Integer delete(Integer id); }
StudentMapperImpl实现类
package com.itheima.mapper.impl; /* 持久层实现类 */ public class StudentMapperImpl implements StudentMapper { /* 查询所有 */ @Override public List<Student> selectAll() { } /* 根据id查询 */ @Override public Student selectById(Integer id) { } /* 新增功能 */ @Override public Integer insert(Student stu) { } /* 修改功能 */ @Override public Integer update(Student stu) { } /* 删除功能 */ @Override public Integer delete(Integer id) { } }
StudentService接口
package com.itheima.service; import com.itheima.bean.Student; import java.util.List; /* 业务层接口 */ public interface StudentService { //查询所有 public abstract List<Student> selectAll(); //根据id查询 public abstract Student selectById(Integer id); //新增数据 public abstract Integer insert(Student stu); //修改数据 public abstract Integer update(Student stu); //删除数据 public abstract Integer delete(Integer id); }
StudentServiceImpl实现类
package com.itheima.service.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.mapper.impl.StudentMapperImpl; import com.itheima.service.StudentService; import java.util.List; /* 业务层实现类 */ public class StudentServiceImpl implements StudentService { //建立持久层对象 private StudentMapper mapper = new StudentMapperImpl(); @Override public List<Student> selectAll() { return mapper.selectAll(); } @Override public Student selectById(Integer id) { return mapper.selectById(id); } @Override public Integer insert(Student stu) { return mapper.insert(stu); } @Override public Integer update(Student stu) { return mapper.update(stu); } @Override public Integer delete(Integer id) { return mapper.delete(id); } }
StudentController测试类:
package com.itheima.controller; import com.itheima.bean.Student; import com.itheima.service.StudentService; import com.itheima.service.impl.StudentServiceImpl; import org.junit.Test; import java.util.List; /* 控制层测试类 */ public class StudentController { //建立业务层对象 private StudentService service = new StudentServiceImpl(); //查询所有功能测试 @Test public void selectAll() { List<Student> students = service.selectAll(); for (Student stu : students) { System.out.println(stu); } } //根据id查询功能测试 @Test public void selectById() { Student stu = service.selectById(3); System.out.println(stu); } //新增功能测试 @Test public void insert() { Student stu = new Student(4,"赵六",26); Integer result = service.insert(stu); System.out.println(result); } //修改功能测试 @Test public void update() { Student stu = new Student(4,"赵六",16); Integer result = service.update(stu); System.out.println(result); } //删除功能测试 @Test public void delete() { Integer result = service.delete(4); System.out.println(result); } }
工具类抽取:
package com.itheima.utils; 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.IOException; /* 工具类 */ public class MyBatisUtils { // 私有构造方法 private MyBatisUtils(){} // 声明链接工厂对象 private static SqlSessionFactory sqlSessionFactory; // 静态代码块,读取核心配置文件并工厂对象赋值 static { try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("MyBatisConfig.xml")); } catch (IOException e) { e.printStackTrace(); } } // 提供静态方法,返回SqlSession对象 public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } }
StudentMapperImpl代码:
package com.itheima.mapper.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import java.util.List; /* 持久层实现类 */ public class StudentMapperImpl implements StudentMapper { /* 查询所有 */ @Override public List<Student> selectAll() { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 List<Student> list = sqlSession.selectList("StudentMapper.selectAll"); // 释放资源 sqlSession.close(); // 返回结果 return list; } /* 根据id查询 */ @Override public Student selectById(Integer id) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Student stu = sqlSession.selectOne("StudentMapper.selectById", id); // 释放资源 sqlSession.close(); // 返回结果 return stu; } /* 新增功能 */ @Override public Integer insert(Student stu) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Integer result = sqlSession.insert("StudentMapper.insert", stu); // 释放资源 sqlSession.close(); // 返回结果 return result; } /* 修改功能 */ @Override public Integer update(Student stu) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Integer result = sqlSession.update("StudentMapper.update", stu); // 释放资源 sqlSession.close(); // 返回结果 return result; } /* 删除功能 */ @Override public Integer delete(Integer id) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Integer result = sqlSession.delete("StudentMapper.delete", id); // 释放资源 sqlSession.close(); // 返回结果 return result; } /* 查询指定的数据表 */ @Override public List<Student> selectByTableName(String tableName) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 List<Student> list = sqlSession.selectList("StudentMapper.selectByTableName",tableName); // 释放资源 sqlSession.close(); // 返回结果 return list; } /* 模糊查询 */ @Override public List<Student> selectLike(String condition) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 List<Student> list = sqlSession.selectList("StudentMapper.selectLike",condition); // 释放资源 sqlSession.close(); // 返回结果 return list; } }
在平常开发过程当中,排查问题时不免须要输出 MyBatis 真正执行的 SQL 语句、参数、结果等信息,咱们就能够借助 LOG4J 的功能来实现执行信息的输出。
使用步骤:
导入 jar 包:“01-MyBatis基础\资料\jar包\log4j-1.2.17.jar”
修改核心配置文件:MyBatisConfig.xml
<!--配置LOG4J:如下name和value是固定写法--> <settings> <setting name="logImpl" value="log4j"/> </settings>
在 src 下编写 LOG4J 配置文件 : log4j.properties (配置文件名字也是固定写法)
# Global logging configuration # 日志的四个级别,从高到低:ERROR(错误信息) WARN(警告信息) INFO(普通讯息) DEBUG(调试信息,推荐使用) # stdout:输出到控制台 log4j.rootLogger=DEBUG, stdout # 输出格式 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
效果
错误:
Caused by: org.xml.sax.SAXParseException; lineNumber: 41; columnNumber: 17; 元素类型为 "configuration" 的内容必须匹配 "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"。
这个是由于configuration下的节点顺序是有要求的,settings必须是在properties下,放在其余位置会报错。