jdbc:
1)优点:简单易学,上手快,非常灵活构建SQL,效率高
2)缺点:代码繁琐,难以写出高质量的代码(例如:资源的释放,SQL注入安全性等)
开发者既要写业务逻辑,又要写对象的创建和销毁,必须管底层具体数据库的语法
(例如:分页)。
3)适合于超大批量数据的操作,速度快
hibernate:
1)优点:不用写SQL,完全以面向对象的方式设计和访问,不用管底层具体数据库的语法,(例如:分页)便于理解。
2)缺点:处理复杂业务时,灵活度差, 复杂的HQL难写难理解,例如多表查询的HQL语句
3)适合于中小批量数据的操作,速度慢
为什么要用mybatis?
1)基于上述二种支持,我们需要在中间找到一个平衡点呢?结合它们的优点,摒弃它们的缺点,
这就是myBatis,现今myBatis被广泛的企业所采用。
什么是mybatis?
1)MyBatis 本是apache的一个开源项目iBatis,2010年这个项目由apachesoftware foundation 迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。
2)iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQLMaps和DataAccess Objects(DAO)
3)jdbc/dbutils/springdao,hibernate/springorm,mybaits同属于ORM解决方案之一
如何使用mybatis?
首先创建一个web项目,导入mybatis相关的jar包
下面是数据库驱动包
然后项目结构如下:
首先我们在数据库中创建相应的表
mysql
create table students(
id int(5) primary key,
name varchar(10),
sal double(8,2)
);
oracle
create table students(
id number(5) primary key,
name varchar2(10),
sal number(8,2)
);
然后创建实体类Student
package cn.qblank.entity;
public class Student {
private int id;
private String name;
private double sal;
public Student(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Student(int id, String name, double sal) {
super();
this.id = id;
this.name = name;
this.sal = sal;
}
}
在entity目录下创建一个StudentMapper.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:名称 空间,必须唯一 -->
<mapper namespace="cn.qblank.entity.Student">
<!--
resultMap标签:映射实体和表
type:表示实体全路径
id:表示result的唯一标识
-->
<resultMap type="student" id="studentMap">
<!-- 实体属性property 表属性:column -->
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="sal" column="sal"/>
</resultMap>
<!--
insert标签:要书写insert这么一个sql语句
id属性:为insert这么一个sql语句取一个任意唯一的名字
parameterType:要执行的dao中的方法的参数,如果是类的话,必须使用全路径类
-->
<insert id="add1">
insert into students(id,name,sal) values(1,'evan_qb',7000)
</insert>
<insert id="add2" parameterType="cn.qblank.entity.Student">
insert into students(id,name,sal) values(#{id},#{name},#{sal})
</insert>
</mapper>
然后再src目录下创建总配置文件mybatis.xml、以及数据库配置文件db.properties
<?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>
<!-- 加载类路径下的属性 -->
<properties resource="db.properties"></properties>
<!-- 设置类型别名 -->
<typeAliases>
<typeAlias type="cn.qblank.entity.Student" alias="student"/>
</typeAliases>
<!-- 设置一个默认的连接配置 -->
<environments default="mysql_developer">
<environment id="mysql_developer">
<!-- 进行事务管理 -->
<transactionManager type="jdbc"></transactionManager>
<!-- 使用连接池方式来获取连接 -->
<dataSource type="pooled">
<!-- 配置数据库的连接配置 -->
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
<environment id="oracle_developer">
<!-- 进行事务管理 -->
<transactionManager type="jdbc"></transactionManager>
<!-- 使用连接池方式获取连接 -->
<dataSource type="pooled">
<!-- 数据库连接池配置 -->
<property name="driver" value="${oracle.driver}"/>
<property name="url" value="${oracle.url}"/>
<property name="username" value="${oracle.username}"/>
<property name="password" value="${oracle.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="cn/qblank/dao/StudentMapper.xml"/>
</mappers>
</configuration>
在util包下创建MybatisUtil工具类用于创建SqlSession和关闭SqlSession
package cn.qblank.util;
import java.io.IOException;
import java.io.Reader;
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 MybatisUtil {
//创建工厂类
private static SqlSessionFactory sqlSessionFactory;
private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
/**
* 加载配置文件mybatis.xml
*/
static{
try {
Reader reader = Resources.getResourceAsReader("mybatis.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 禁止外界new出对象
*/
private MybatisUtil(){}
/**
* 获取SqlSession
* @return
*/
public static SqlSession getSqlSession(){
//从当前线程中获取SqlSession对象
SqlSession sqlSession = threadLocal.get();
//如果为空
if (sqlSession == null) {
//通过SqlSessionFactory获取对象
sqlSession = sqlSessionFactory.openSession();
//将SqlSession对象和当前线程绑定在一起
threadLocal.set(sqlSession);
}
return sqlSession;
}
/**
* 关闭SqlSession并与当前线程解绑
*/
public static void closeSqlSession(){
//先从当前线程中获取sqlSession对象
SqlSession sqlSession = threadLocal.get();
if (sqlSession != null) {
//关闭sqlSession
sqlSession.close();
//解绑
threadLocal.remove();
}
}
}
接下来我们需要用到动态代理(JDK代理),所以我们首先创建一个IStudentDao接口
package cn.qblank.dao;
import cn.qblank.entity.Student;
/**
* 接口
* @author Administrator
*
*/
public interface IStudentDao {
void add1();
void add2(Student student);
}
在proxy包下创建代理工厂类
package cn.qblank.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.ibatis.session.SqlSession;
import cn.qblank.util.MybatisUtil;
public class ProxyFactory {
//维护一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
//给目标对象生成地代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().
//指定当前类使用的加载器
getClassLoader()
//目标对象实现的接口
,target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
SqlSession sqlSession = null;
Object returnValue = null;
try {
sqlSession = MybatisUtil.getSqlSession();
//开启事务(默认开始)
//执行方法
returnValue = method.invoke(target, args);
//事务提交
sqlSession.commit();
System.out.println("代理成功!!!!!");
} catch (Exception e) {
e.printStackTrace();
//事务回滚
sqlSession.rollback();
}finally{
MybatisUtil.closeSqlSession();
}
return returnValue;
}
});
}
}
创建一个StudentDao实现IStudentDao接口
package cn.qblank.dao;
import org.apache.ibatis.session.SqlSession;
import cn.qblank.entity.Student;
import cn.qblank.proxy.ProxyFactory;
import cn.qblank.util.MybatisUtil;
public class StudentDao implements IStudentDao{
private SqlSession sqlSession = null;
public static void main(String[] args) throws Exception {
//创建目标对象
IStudentDao dao = new StudentDao();
//构建代理对象
IStudentDao proxy = (IStudentDao) new ProxyFactory(dao).getProxyInstance();
proxy.add1();
proxy.add2(new Student(2, "evan_qb2", 4000.0));
}
/**
* 添加学生 实现方式一:无参
* @throws Exception
*/
@Override
public void add1(){
//次数使用动态JDK代理
sqlSession = MybatisUtil.getSqlSession();
//读取StudentMapping中的Sql语句
int i = sqlSession.insert("cn.qblank.entity.Student.add1");
System.out.println("影响了" + i + "行");
}
/**
* 添加学生 方式一:有参数方法:
* @throws Exception
*/
@Override
public void add2(Student student){
//次数使用动态JDK代理
sqlSession = MybatisUtil.getSqlSession();
//读取StudentMapper.xml映射文件中的SQL语句
int i = sqlSession.insert(Student.class.getName() + ".add2",student);
System.out.println("影响了" + i + "行");
}
}
然后我们通过StudentDao下的main方法运行一下,结果如下:
可以看到插入成功,这样我们就完成了第一个mybatis案例
总结下mybatis的工作流程
1) 通过Reader对象读取src目录下的mybatis.xml配置文件(名字可以随便写)
2) 通过SqlSessionFactoryBuilder对象创建SqlSessionFactory对象(SqlSession工厂)
3) 从当前线程中获取SqlSession对象
4) 事务开始,在mybatis中默认
5) 通过SqlSession对象读取StudentMapper.xml映射文件中的操作编号,从而读取sql语句
6) 事务提交(提交必写)
7) 关闭SqlSession对象,并且分开当前线程与SqlSession对象,让GC尽早回收。