主动记录
在软件工程中,主动记录模式(active record pattern)是一种架构模式,可见于在关系数据库中存储内存中对象的软件中。它在Martin Fowler的2003年著《企业应用架构的模式》书中命名[1]。符合这个模式的对象的接口将包括函数比如插入、更新和删除,加上直接对应于在底层数据库表格中列的或多或少的属性。
主动记录模式是访问在数据库中的数据的一种方式。数据库表或视图被包装入类。因此,对象实例被连结到这个表格的一个单一行。在一个对象建立之后,在保存时将一个新行增加到表格中。加载的任何对象都从数据库得到它的信息。在一个对象被更新的时候,在表格中对应的行也被更新。包装类为在表格或视图中的每个列都实现访问器方法或属性。
这个模式常用于对象持久化工具和对象关系映射(ORM)之中。典型的,外键联系也通过一个属性而被显露为适当类型的一个对象实例。
实现
[编辑]这个概念的实现可以在很多编程环境中的各种框架中找到。例如,如果在数据库中有一个表格parts,它具有列name(字符串类型)和price(数值类型),而主动记录模式用类Part来实现,伪码为:
part = new Part() part.name = "Sample part" part.price = 123.45 part.save()
它在parts表格中建立有给定值的一个新行,并且粗略的等价于SQL命令:
INSERT INTO parts (name, price) VALUES ('Sample part', 123.45);
反过来,这个类可以被用来查询这个数据库:
b = Part.find_first("name", "gearbox")
这会找到一个新Part对象,基于在parts表格中其name列的值为"gearbox"的第一个匹配行。使用的SQL命令可能类似于下面所列,具体依赖于这个数据库的SQL实现细节:
SELECT * FROM parts WHERE name = 'gearbox' LIMIT 1; -- MySQL or PostgreSQL
例子
[编辑]下面的例子是Java中的一个主动记录对象User。这里的User类是模型和数据访问对象二者,并且提供save()、find()和delete()方法。
package org.wikipedia.examples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class User {
private int id;
private String name;
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public void save() {
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password")) {
if (this.id == 0) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
stmt.setString(1, this.name);
stmt.setString(2, this.email);
stmt.executeUpdate();
ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()) {
this.id = rs.getInt(1);
}
}
} else {
String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, this.name);
stmt.setString(2, this.email);
stmt.setInt(3, this.id);
stmt.executeUpdate();
}
}
} catch (SQLException e) {
System.err.printf("A SQLException occurred: %s%n", e.getMessage());
e.printStackTrace();
}
}
public static User find(int id) {
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password")) {
String sql = "SELECT * FROM users WHERE id = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
User user = new User(rs.getString("name"), rs.getString("email"));
user.setId(rs.getInt("id"));
return user;
}
}
} catch (SQLException e) {
System.err.printf("A SQLException occurred: %s%n", e.getMessage());
e.printStackTrace();
}
return null;
}
public void delete() {
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password")) {
String sql = "DELETE FROM users WHERE id = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, this.id);
stmt.executeUpdate();
}
} catch (SQLException e) {
System.err.printf("A SQLException occurred: %s%n", e.getMessage());
e.printStackTrace();
}
}
}
主动记录框架
[编辑]主动记录框架一般兼有ORM框架的功能,但主动记录不是简单的ORM。关系型数据库往往通过外键来表述实体的联系,主动记录在数据源层面上也将这种联系映射为对象的关联和聚集。著名的例子是解决方案堆栈Web开发框架Ruby on Rails,其默认使用一个纯Ruby写成的主动记录框架来驱动MVC中的模型层。此外还有:
类似模式
[编辑]主动记录和行数据门路十分相似,但前者是领域模型模式,后者只是一种数据源模式。主动记录适合非常简单的领域需求,尤其在领域模型和数据库模型十分相似的情况下。如果遇到更加复杂的领域模型结构(例如用到继承、策略的领域模型),往往需要使用分离数据源的领域模型,结合数据映射器使用。
参见
[编辑]资料来源
[编辑]- ^ Fowler, Martin. Patterns of enterprise application architecture. Addison-Wesley. 2003 [2020-11-07]. ISBN 978-0-321-12742-6. (原始内容存档于2021-11-24).
承载数据和行为二者的对象。多数这种数据是持久化的并需要被存储在数据库中。主动记录使用最明显的方式,将数据访问逻辑放置在领域对象中。这种方式下所有人都知道如何读和写他们的数据进出数据库。
- ^ Orator - An ActiveRecord ORM for Python. [2020-11-08]. (原始内容存档于2020-12-16).
- ^ ObjectiveSql (页面存档备份,存于互联网档案馆)
- ^ JAVA 极速WEB+ORM框架 JFinal. [2020-11-08]. (原始内容存档于2020-11-21).
外部链接
[编辑]