8.1. ORM概述
8.1.1. ORM的概念
在面向对象程序中,数据是由对象的属性体现的,而在关系数据库中,数据是以表的形式存储的。当我们需要进行数据持久化时,就不可避免的在二者之间进行转换,也就是把对象的属性值映射为数据库表中某一字段值或者相反。
比如,我们的程序中有Customer这个实体类:
public class Customer {private int id;private String name;private String mobilePhone;private LocalDate birthDate;// getters and setters// ...}
数据库中对应的有一个Customer表:
| 字段名 | 字段类型 | 其它 |
|---|---|---|
| id | integer | PK, auto_increment |
| name | nvarchar(50) | |
| mobilePhone | nvarchar(20) | |
| birthDate | datetime |
我们可以通过下面的代码把从数据库中查询出的数据赋值给Customer对象的属性:
public class DBUtil {public static List<Customer> getCustomers() throws Exception {// 加载数据库驱动程序,在新版本的MySql驱动程序中已经不需要了// Class.forName("com.mysql.jdbc.Driver");// 建立连接String url = "jdbc:mysql://localhost:3306/tmall?useUnicode=true&characterEncoding=utf8&useSSL=true";Connection connection = DriverManager.getConnection(url, "root", "hrbust123");// 查询,返回结果集Statement statement = connection.createStatement();String sql = "select * from Customer";ResultSet resultSet = statement.executeQuery(sql);// 将结果映射为对象的属性List<Customer> customers = new ArrayList<>();while(resultSet.next()) {Customer customer = new Customer();customer.setId(resultSet.getInt("id"));customer.setName(resultSet.getString("name"));customer.setMobilePhone(resultSet.getString("mobilePhone"));customer.setBirthDate(resultSet.getDate("birthDate").toLocalDate());customers.add(customer);}// 释放资源resultSet.close();statement.close();connection.close();return customers;}}
这个过程就是关系到对象的映射,属于ORM中R->M的部分。当然,在实际应用中,还需要编写相应的M->R部分,将对象中的属性值保存到数据库中。在使用上面代码的过程中会存在几个问题:
- 存在大量重复代码,如打开/关闭数据库连接,对象属性和数据库字段互相赋值,错误处理,事务处理等等。
- 有大量细节需要处理,如数据库数据类型和编程语言数据类型匹配问题。
- 有大量与具体DBMS相关的代码,不利于系统维护和扩展。
对象关系映射(Object Relational Mapping,简称ORM)模式是一种解决系统对象与关系数据库数据互转换问题的技术,使得开发人员不必再去关心数据库的读写细节以及对象的属性和数据库表中字段的对应问题,从大量重复代码中解脱出来,专注于业务逻辑代码的编写。同时,有些ORM框架还可以帮助生成并优化SQL语句,管理事务、并发等,使数据库的使用更高效。
8.1.2. 流行的ORM框架
市面上流行的ORM框架不计其数,有的小巧灵活,仅进行对象和数据库表的双向映射功能,有的结构复杂功能强大,从关系映射到事务管理到查询。如:
- .Net领域:EntityFramework.core、Dapper等
- Python领域:SQLAlchemy
- Java领域:Hibernate、MyBatis、Spring Data JPA
