此模式属于 数据源架构模式 目录,此目录属于 企业应用程序体系结构模式。
目的
一个对象,充当数据源中单个记录的网关。每行有一个实例。
这里 Gateway 指封装对外部系统或资源的访问的对象。
该对象不包含域逻辑方法。如果引入其他方法(特别是域逻辑),则该对象将成为活动记录模式。
如何运作
行数据网关充当完全模拟单个记录的对象,例如一个数据库行。例如,person类有一个id、firstname和lastname字段。
public class Person{ private int id; private String firstName; private String lastName; // Getter and Setter methods }
|
Person Java类的Person表
ID 名字 姓
1 拉梅什 Fadatare
此模式保存有关行的数据,以便客户端可以直接访问行数据网关。网关充当每行数据的良好接口。这种方法特别适用于Transaction Scripts。
说明
在内存对象中嵌入数据库访问代码会可能会带来一些缺点。首先,如果内存中的对象有自己的业务逻辑,那么添加数据库操作代码会增加复杂性。其次,测试也很尴尬,因为如果内存中的对象绑定到数据库,由于所有数据库访问,测试运行速度较慢。您可能需要访问多个数据库,其中包含所有这些令人讨厌的SQL小变化。
行数据网关为您提供了与记录结构中的记录完全相似的对象,但可以使用编程语言的常规机制访问这些对象。数据源访问的所有详细信息都隐藏在此接口后面。
何时使用它
此行数据网关广泛用于事务脚本模式。在这种情况下,它很好地分解了数据库访问代码,并允许不同的事务脚本轻松地重用它。
示例代码
让我们为PersonGateway的示例代码创建一个类图, 以演示这种模式。
这是行数据网关的一个例子 。这是一个简单的人员表。
create table people (ID int primary key, lastname varchar, firstname varchar, number_of_dependents int)
|
PersonGateway是这个表的门户。它从数据字段和访问器开始。
class PersonGateway...
private String lastName; private String firstName; private int numberOfDependents; public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public int getNumberOfDependents() { return numberOfDependents; } public void setNumberOfDependents(int numberOfDependents) { this.numberOfDependents = numberOfDependents; }
|
网关类本身可以处理更新和插入。
class PersonGateway...
private static final String updateStatementString = "UPDATE people " + " set lastname = ?, firstname = ?, number_of_dependents = ? " + " where id = ?"; public void update() { PreparedStatement updateStatement = null; try { updateStatement = DB.prepare(updateStatementString); updateStatement.setString(1, lastName); updateStatement.setString(2, firstName); updateStatement.setInt(3, numberOfDependents); updateStatement.setInt(4, getID().intValue()); updateStatement.execute(); } catch (Exception e) { throw new ApplicationException(e); } finally {DB.cleanUp(updateStatement); } } private static final String insertStatementString = "INSERT INTO people VALUES (?, ?, ?, ?)"; public Long insert() { PreparedStatement insertStatement = null; try { insertStatement = DB.prepare(insertStatementString); setID(findNextDatabaseId()); insertStatement.setInt(1, getID().intValue()); insertStatement.setString(2, lastName); insertStatement.setString(3, firstName); insertStatement.setInt(4, numberOfDependents); insertStatement.execute(); Registry.addPerson(this); return getID(); } catch (SQLException e) { throw new ApplicationException(e); } finally {DB.cleanUp(insertStatement); } }
|
要从数据库中提取人员行,我们有一个单独的 PersonFinder。它与网关一起创建新的网关对象。。
class PersonFinder...
private final static String findStatementString = "SELECT id, lastname, firstname, number_of_dependents " + " from people " + " WHERE id = ?"; public PersonGateway find(Long id) { PersonGateway result = (PersonGateway) Registry.getPerson(id); if (result != null) return result; PreparedStatement findStatement = null; ResultSet rs = null; try { findStatement = DB.prepare(findStatementString); findStatement.setLong(1, id.longValue()); rs = findStatement.executeQuery(); rs.next(); result = PersonGateway.load(rs); return result; } catch (SQLException e) { throw new ApplicationException(e); } finally {DB.cleanUp(findStatement, rs); } } public PersonGateway find(long id) { return find(new Long(id)); } class PersonGateway...
public static PersonGateway load(ResultSet rs) throws SQLException { Long id = new Long(rs.getLong(1)); PersonGateway result = (PersonGateway) Registry.getPerson(id); if (result != null) return result; String lastNameArg = rs.getString(2); String firstNameArg = rs.getString(3); int numDependentsArg = rs.getInt(4); result = new PersonGateway(id, lastNameArg, firstNameArg, numDependentsArg); Registry.addPerson(result); return result; }
|
为了根据某些标准找到多个人,我们可以提供一个合适的查找方法。
class PersonFinder...
private static final String findResponsibleStatement = "SELECT id, lastname, firstname, number_of_dependents " + " from people " + " WHERE number_of_dependents > 0"; public List findResponsibles() { List result = new ArrayList(); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = DB.prepare(findResponsibleStatement); rs = stmt.executeQuery(); while (rs.next()) { result.add(PersonGateway.load(rs)); } return result; } catch (SQLException e) { throw new ApplicationException(e); } finally {DB.cleanUp(stmt, rs); } }
|
查找器使用注册表模式保存标识映射。
我们现在可以使用事务脚本模式中的网关
PersonFinder finder = new PersonFinder(); Iterator people = finder.findResponsibles().iterator(); StringBuffer result = new StringBuffer(); while (people.hasNext()) { PersonGateway each = (PersonGateway) people.next(); result.append(each.getLastName()); result.append(" "); result.append(each.getFirstName()); result.append(" "); result.append(String.valueOf(each.getNumberOfDependents())); result.append("
} return result.toString();
|