JDBC
Java程序是通过JDBC(Java Data Base Connectivity)连接数据库的,JDBC是由SUN公司提出的一系列规范,但是它只定义了接口的规范,而具体的实现是交给了各个数据库厂商去实现的,JDBC是一种典型的桥接模式
JDBC编程步骤
- 使用JDBC编程需要连接数据库,注册驱动和数据库信息
- 操作Connection,打开Statement对象
- 通过Statement执行SQL,返回结果到ResultSet对象
- 使用ResultSet读取数据,然后通过代码转换为具体的POJO对象
- 关闭数据库相关资源
示例
import java.sql.*;
class StudentDao {
private static Connection getConn() {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/samp_db";
String username = "root";
String password = "";
Connection conn = null;
try {
Class.forName(driver); //classLoader,加载对应驱动
conn = (Connection) DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
private static int insert(Student student) {
Connection conn = getConn();
int i = 0;
String sql = "insert into students (Name,Sex,Age) values(?,?,?)";
PreparedStatement pstmt;
try {
pstmt = (PreparedStatement) conn.prepareStatement(sql);
pstmt.setString(1, student.getName());
pstmt.setString(2, student.getSex());
pstmt.setString(3, student.getAge());
i = pstmt.executeUpdate();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
return i;
}
private static List<Student> getAllStudents() {
Statement stmt = null;
Statement stmt = null;
List<Student> students = new ArrayList<>();
try {
stmt = conn.createStatement();
String sql = "SELECT * FROM students";
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
//Retrieve by column name
int id = rs.getInt("id");
int age = rs.getInt("age");
Student student = new Student();
student.setId(id);
student.setAge(age);
students.add(student);
}
rs.close();
} catch(SQLException e) {
//Handle errors for JDBC
e.printStackTrace();
} catch(Exception e) {
//Handle errors for Class.forName
e.printStackTrace();
} finally {
try {
if(stmt!=null)
stmt.close();
} catch(SQLException e) {
// nothing we can do
}
try {
if(conn!=null)
conn.close();
} catch(SQLException e){
e.printStackTrace();
}
}
}
}
缺点
- 工作量大:数据库到 POJO 的转换需要手动写代码解决
- 编程复杂:各种异常处理
ORM模型
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
JPA是 ORM 框架标准,主流的 ORM 框架都实现了这个标准。
Java 中目前最流行的 ORM 包括:Hibernate,Mybatis(实际是 OXM) 等。
Hibernate
Hibernate优势
- 支持 JPA,全自动框架,通过对象关系模型对数据库表操作
- 可移植性好
- 支持二级缓存,可以使用三方缓存
- 消除了代码的映射规则,它全部被分离到了XML或者注解里面去配置
- 无需再管理数据库连接,它也可以配置在XML里面
- 一个会话中,不要操作多个对象,只要操作Session对象即可
- 关闭资源只需要关闭一个Session便可
Hibernate 的缺点
- 全表映射带来了不便,比如更新时需要发送所有的字段
- 无法根据不同的条件组装不同的SQL
- 对多表关联和复杂SQL查询支持较差,需要自己写SQL,返回后,需要自己将数据组装为POJO
- 不能有效支持存储过程
- 虽然有HQL,但是性能较差,大型互联网系统往往需要优化SQL,而Hibernate做不到
- 学习门槛高,对使用者的设计能力有一定要求
Mybatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
Mybaits的前身是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了 google code 并且改名为Mybatis,2013年11月迁移到Github,目前mybaits是由Github维护的
最新版本:3.5.0
iBatis一词来源于“internet”和“abatis”的组合
官网 中文官网
优点
- 易于上手,对数据模型要求低的项目来说,非常好用
- 提供丰富的 XML 标签,支持动态 SQL
- 执行效率高于 Hibernate
- 拥有映射标签,支持对象和数据库的 ORM 字段关系映射
- sql 写在 xml 里面,便于统一管理和 SQL 优化,有效解除 SQL 与代码的耦合
缺点
- 可移植性差
- XML 中标签 ID 是唯一的,Dao 层不支持方法重载
- 日志功能很弱
- 动态 SQL 不便于调试
MyBatis VS Hibernate
Mybatis是OXM 框架而不是ORM框架,当然ORM和Mybatis都是持久层框架。
-
Hibernate是全自动ORM框架,而Mybatis是半自动的。hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理。
-
hibernate数据库移植性远大于mybatis。 hibernate通过它强大的映射结构和hql语言,大大降低了对象与数据库(oracle、mysql等)的耦合性,而mybatis由于需要手写sql,因此与数据库的耦合性直接取决于程序员写sql的方法,如果sql不具通用性而用了很多某数据库特性的sql语句的话,移植性也会随之降低很多,成本很高。
-
hibernate拥有完整的日志系统,mybatis则欠缺一些。hibernate日志系统非常健全,涉及广泛,包括:sql记录、关系异常、优化警告、缓存提示、脏数据警告等;而mybatis则除了基本记录功能外,功能薄弱很多。
-
mybatis相比hibernate需要关心很多细节。hibernate配置要比mybatis复杂的多,学习成本也比mybatis高。但也正因为mybatis使用简单,才导致它要比hibernate关心很多技术细节。mybatis由于不用考虑很多细节,开发模式上与传统JDBC区别很小,因此很容易上手并开发项目,但忽略细节会导致项目前期bug较多,因而开发出相对稳定的软件很慢,而开发出软件却很快,这对于需求非常快的互联网企业来书非常重要,这也是采用 mybatis 的主要原因
-
sql直接优化上:mybatis要比hibernate方便很多。由于mybatis的sql都是写在xml里,因此优化sql比hibernate方便很多。而hibernate的sql很多都是自动生成的,无法直接维护sql;虽有hql,但功能还是不及sql强大,见到报表等变态需求时,hql也歇菜,也就是说hql是有局限的;hibernate虽然也支持原生sql,但开发模式上却与orm不同,需要转换思维,因此使用上不是非常方便。总之写sql的灵活度上hibernate不及mybatis。
-
现在的大型系统几乎全是分布式的,mybatis在分布式系统里面是当做业务代码的一个基础组件来用,相当于一个无状态的服务,hibernate就不合适了,耦合度高还麻烦
总结
Mybatis:小巧、方便、高效、简单、直接、半自动化
Hibernate:强大、方便、高效、复杂、间接、全自动化
彩蛋
为什么国内流行mybatis,国外反而多用hibernate?
https://www.zhihu.com/question/309662829/answer/579433240