在上一篇文章里面,我们对JDBC的知识进行了复习整理,对JDBC的操作也进行了很多优化。那么今天我们就来学习第一个框架:Mybatis
MyBatis 本是Apache的一个开源项目iBatis, 2010年这个项目由Apache Software Foundation 迁移到了Google Code,且改名为MyBatis 。2013年11月迁移到GitHub。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
关键字:框架、ORM、持久层
JDBC的缺点:需要手动的完成面向对象的Java语言、面向关系的数据库之间数据的转换,代码繁琐无技术含量,影响了开发效率。
JDBC查询需要手动的将结果集的列数据转换为Java对象的属性;而添加操作时需要手动将Java对象的属性转换为数据库表的列字段。
关于面向对象的Java语言、面向关系的数据库之间数据的转换必须要做,问题在于这个转换是否可以不由开发者来做。可以的。ORM框架就是专门来做这个问题的,相当于在面向对象语言和关系数据库之间搭建一个桥梁。
ORM,Object-Relationl Mapping,对象关系映射,它的作用是在关系型数据库和对象之间作一个映射,这样我们在具体的操作数据库的时候,只要像平时操作对象一样操作它就可以了,ORM框架会根据映射完成对数据库的操作,就不需要再去和复杂的SQL语句打交道了。
另外学习ORM必须知道两个概念:持久化、持久层
持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。
持久层(Persistence Layer),即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面,将数据使用者和数据实体相关联。之前使用JDBC访问数据库的DAO层,后面采用MyBatis访问数据库的mapper层,就是持久层。
Mybatis是一持久层的款半自动的ORM映射框架
Hibernate是一个全自动的ORM框架。因为Hibernate创建了Java对象和数据库表之间的完整映射,可以完全以面向对象的思想来操作数据库,程序员不需要手写SQL语句,而MyBatis中还需要手写SQL语句,所以是半自动化的,工作量要大于Hibernate。
MyBatis需要手写SQL语句,所以工作量要大于Hibernate。但是也正是由于自定义SQL语句,所以其灵活性、可优化性就超过了Hibernate。
Hibernate封装了SQL语句,由开发者对对象操作,Hibernate来生成SQL语句。虽然也可以通过映射配置来控制生成的SQL语句,但是对于要生成复杂的SQL语句,很难实现,或者实现后导致性能的丢失。
MyBatis对存储过程可提供很好的支持。另外MyBatis的开发工作量大不意味着学习成本大。对于新手,学习Hibernate时间成本比Mybatis大很多,Mybatis很快就上手了。
总之,因为MySQL具有相对轻量级,封装少、映射多样化、支持存储过程、可以进行SQL语句优化等特点,符合互联网高并发、大数据、高性能、高响应的要求,使它取代Hibernate成为了Java互联网中首选的持久框架。而对于对性能要求不高的比如内部管理系统、ERP等可以使用Hibernate。
编号 | 元素列表 | 作用 |
1 | mybatis-3.5.2.jar | Mybatis核心jar包 |
2 | ant-1.10.3.jar | 将软件编译、测试、部署等步骤联系在一起加以自动化的一个软件构建工具 |
3 | ant-launcher-1.10.3.jar | 将软件编译、测试、部署等步骤联系在一起加以自动化的一个软件构建工具 |
4 | asm-7.0.jar | 代码生成,代码混淆,代码转换等等以字节码为操作目标的工作,一定程度上类似javac的功能 |
5 | cglib-3.2.10.jar | 实现动态代理的技术,延迟加载时使用 |
6 | javassist-3.24.1-GA.jar | 可用来检查、”动态”修改及创建 Java类。功能与JDK自带反射功能类似,但比反射功能更强大 |
7 | ognl-3.2.10.jar | 对象导航图语言的缩写,功能强大的表达式语言工具包。在动态SQL和${param}中使用 |
8 | commons-logging-1.2.jar | 日志包 |
9 | slf4j-api-1.7.26.jar | 日志包 |
10 | slf4j-log4j12-1.7.26.jar | 日志包 |
11 | log4j-1.2.17.jar | 日志包 |
12 | log4j-api-2.11.2.jar | 日志包 |
13 | log4j-core-2.11.2.jar | 日志包 |
在src下定义MyBatis的配置文件,无固定名称。但是大多数情况下用Mybatis.xml
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/alvin/mapper/StudentMapper.xml"/>
mappers>
configuration>
<mapper namespace="com.alvin.mapper.StudentMapper">
<select id="stu" resultType="com.alvin.pojo.Student">
select * from student;
select>
mapper>
public class Test {
public static void main(String[] args) throws IOException {
//1获取sqlsession
//SqlSessionFactory创建工具 专门用户创建SqlSessionFactory
SqlSessionFactoryBuilder ssfb =new SqlSessionFactoryBuilder();
// SqlSessionFactory sql语句会话对象工厂,专门用于生产SqlSession对象
InputStream is = Resources.getResourceAsStream("mybatis.xml");
// build方法中需要传入一个输入流作为参数 输入流要指向我们的mybatis核心配置文件
SqlSessionFactory factory=ssfb.build(is);
//sql语句会话对象 专门用于执行sql语句和返回结果
SqlSession sqlSession=factory.openSession();
//2用sqlsession执行sql语句,完成映射关系处理
// selectOne中方的是要执行的sql语句的id
List<Student>list = sqlSession.selectList("stu");
//3关闭sqlsession 释放资源
sqlSession.close();
//遍历结果
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
项目的搭建很费劲,搭建完毕之后,后面所有的增删改查就变的简单了,套路在mapper映射文件定义一个sql语句,使用sqlsession调用sql语句即可,再也不用编写原生JDBC代码了,再也不用手动处理ResultSet 封装成java对象. 再也不用手动的设置sql语句的参数了,完全由mybatis自动完成映射处理
在mybatis.cfg.xml中配置MyBatis所使用的具体日志实现。如果不指定将自动搜索。可能会搜到log4j,但是如果优先搜到了其他的日志实现呢,所以还是设置为好。这一来log4j就跑不了了。
将log4j.properties文件负责到src下。另外在其中可以将全局的日志级别调高,避免大量debug信息的干扰。同时将对映射文件的操作调低,可以用来显示SQL语句的调试信息。开发阶段,建议启动控制的日志。
#定义全局日志级别调试阶段推荐debug
log4j.rootLogger=debug,stdout
#包级别日志 调试阶段推荐debug
log4j.logger.com.alvin.mapper=debug
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=d:/alvin.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %F %p %m%n
可以查看mybatis核心配置文件中都可以配置哪些东西
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
在mybatis核心配置文件中 emvirment中 通过transactionManager配置事务的处理策略
JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期(比如 Spring 或 JEE 应用服务器的上下文) 默认情况下它会关闭连接。然而一些容器并不希望这样, 因此如果你需要从连接中停止它,将 closeConnection 属性设置为 false. mybatis本身并不做事务的处理,交给其他框架去处理事务,如spring
<typeAliases>
<package name="com.alvin.pojo"/>
typeAliases>
这样返回到到mapper文件里resultType里面就只需要student,而不是com.alvin.pojo.student了(映射文件)
这个时候回到Mybatis.xml
这样下来就简单多了~
前面我们已经写过一遍Mybatis基于List查询,现在我们把一些固定的操作给封装在一个工具类里,省的每次都要写,可以提高开发效率。
public class SqlSessionUtil {
private static SqlSessionFactory factory;
static {
InputStream ins = null;
try {
ins = Resources.getResourceAsStream("mybatis.xml");
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
factory = builder.build(ins);
}
public static SqlSession getSqlSession(boolean autoCommit){
/*
* factory.openSession(true) 事务自动提交
* 如果不传入 true 默认为false
* */
SqlSession sqlSession = factory.openSession(autoCommit);
return sqlSession;
}
//方法重载
public static SqlSession getSqlSession(){
/*
* factory.openSession(true) 事务自动提交
* 如果不传入 true 默认为false
* */
SqlSession sqlSession = factory.openSession();
return sqlSession;
}
}
public class Student {
private String son;
private String realname;
private String password;
private String classname;
private Double score;
//Get Set就不在文章里面写了
}
<mapper namespace="com.alvin.mapper.StudentMapper">
<select id="findall" resultType="student">
select * from student;
select>
<select id="findbyname" resultType="student">
select * from student where realname = #{param};
select>
<select id="findbymap" resultType="student">
select * from student where realname = #{param1} and password = #{param2};
select>
mapper>
public class Test {
public static void main(String[] args) throws IOException {
FindOne();
FindList();
FindMap();
}
//查询单个信息
public static void FindOne(){
//链接工具类
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
//接收数据 前面是id 后面是 #{param} 参数
Student student = sqlSession.selectOne("findbyname","黄贵根");
//关闭sqlSession
sqlSession.close();
//查看结果
System.out.println(student);
}
//查询多个信息
public static void FindMap(){
//链接工具类
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
//输入参数
Map<String,Object> map = new HashMap<>();
//注意:这个时候map的 key 必须和 #{param} 名字相同, 然后根据对应的名字输入对应的value
map.put("param1","黄贵根");
map.put("param2","66666");
//查询
List<Student> list = sqlSession.selectList("findbymap",map);
//关闭sqlSession
sqlSession.close();
//结果:
System.out.println(list);
}
//查询全部信息
public static void FindList(){
//链接工具类
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
//接收
List<Student> list = sqlSession.selectList("findall");
//关闭
sqlSession.close();
//结果:
System.out.println(list);
}
}
好了,关于Mybatis的学习,今天就到这里了!我们下期再见!