DataMapperパターン
* モデルとデータベースの間を取りなすMapperという中間的な構造を持っている
サンプル
DBテーブル/PostgreSQL
person
CREATE TABLE person ( id character(8) NOT NULL, name character varying(100), sex character(1), updatedate timestamp without time zone, CONSTRAINT person_pkey PRIMARY KEY (id) )
Javaソース
BaseDbObject.java
public class BaseDbObject { protected String id; public String getId() { return this.id; } public void setId(String id) { this.id = id; } }
Person.java
import java.sql.Timestamp; public class Person extends BaseDbObject { private String name; private String sex; private Timestamp updatedate; public Person(String id, String name, String sex, Timestamp updatedate) { this.id = id; this.name = name; this.sex = sex; this.updatedate = updatedate; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Timestamp getUpdatedate() { return updatedate; } public void setUpdatedate(Timestamp updatedate) { this.updatedate = updatedate; } }
PersonMapper.java
import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.List; public class PersonMapper extends BaseMapper<Person> { private static final String STATEMENT_FIND = "SELECT * FROM person WHERE id = ?"; private static final String STATEMENT_FIND_BY_NAME = "SELECT * FROM person WHERE name = ?"; private static final String STATEMENT_INSERT = "INSERT INTO person VALUES ( ?, ?, ?, ? )"; private static final String STATEMENT_UPDATE = "UPDATE person SET name = ?, sex = ?, updatedate = ? WHERE id = ?"; private static final String STATEMENT_DELETE = "DELETE FROM person WHERE id = ?"; public PersonMapper() throws ClassNotFoundException, SQLException { super(); } public List<Person> findByName(String name) { try { PreparedStatement pstmt = this.connection.prepareStatement(STATEMENT_FIND_BY_NAME); pstmt.setString(1, name); ResultSet rs = pstmt.executeQuery(); return loadAll(rs); } catch (SQLException e) { throw new RuntimeException(e); } } public void update(Person subject) { try { PreparedStatement pstmt = this.connection.prepareStatement(STATEMENT_UPDATE); pstmt.setString(1, subject.getName()); pstmt.setString(2, subject.getSex()); pstmt.setTimestamp(3, subject.getUpdatedate()); pstmt.setString(4, subject.getId()); pstmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } } public void delete(Person subject) { try { PreparedStatement stmt = this.connection.prepareStatement(STATEMENT_DELETE); stmt.setString(1, subject.getId()); stmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } } @Override protected String findStatement() { return STATEMENT_FIND; } @Override protected String insertStatement() { return STATEMENT_INSERT; } @Override protected Person doLoad(String id, ResultSet rs) throws SQLException { String name = rs.getString(2); String sex = rs.getString(3); Timestamp updatedate = rs.getTimestamp(4); return new Person(id, name, sex, updatedate); } @Override protected void doInsert(Person subject, PreparedStatement pstmt) throws SQLException { pstmt.setString(2, subject.getName()); pstmt.setString(3, subject.getSex()); pstmt.setTimestamp(4, subject.getUpdatedate()); } }
BaseMapper.java
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public abstract class BaseMapper<E extends BaseDbObject> implements IFinder<E> { protected Map<String, E> loadedMap = new HashMap<String, E>(); protected Connection connection; abstract protected String findStatement(); abstract protected String insertStatement(); abstract protected E doLoad(String id, ResultSet rs) throws SQLException; abstract protected void doInsert(E domainObject, PreparedStatement pstmt) throws SQLException; public BaseMapper() throws ClassNotFoundException, SQLException { Class.forName("org.postgresql.Driver"); this.connection = DriverManager.getConnection( "jdbc:postgresql://localhost:5432/Sample", "user", "password"); } @Override public E find(String id) { E domainObject = loadedMap.get(id); if (domainObject != null) { return domainObject; } try { PreparedStatement pstmt = this.connection.prepareStatement(findStatement()); pstmt.setString(1, id); ResultSet rs = pstmt.executeQuery(); rs.next(); domainObject = load(rs); return domainObject; } catch (SQLException e) { throw new RuntimeException(e); } } public void insert(E subject) { try { PreparedStatement pstmt = this.connection.prepareStatement(insertStatement()); pstmt.setString(1, subject.getId()); doInsert(subject, pstmt); pstmt.executeUpdate(); loadedMap.put(subject.getId(), subject); } catch (SQLException e) { throw new RuntimeException(e); } } protected E load(ResultSet rs) throws SQLException { String id = rs.getString(1); if (loadedMap.containsKey(id)) { return loadedMap.get(id); } E domainObjcet = doLoad(id, rs); loadedMap.put(id, domainObjcet); return domainObjcet; } protected List<E> loadAll(ResultSet rs) throws SQLException { List<E> results = new ArrayList<E>(); while (rs.next()) { results.add(load(rs)); } return results; } }
IFinder.java
public interface IFinder<E> { E find(String id); }
Main.java
* 使用者import java.sql.SQLException; import java.sql.Timestamp; import java.util.List; public class Main { public static void main(String[] args) throws ClassNotFoundException, SQLException { PersonMapper personMapper = new PersonMapper(); Person mike = new Person("X0000034", "Mike", "m", new Timestamp(System.currentTimeMillis())); // 追加 personMapper.insert(mike); Person foundMike = personMapper.find("X0000034"); Main.print(foundMike); List<Person> foundMikes = personMapper.findByName("Mike"); for (Person person : foundMikes) { Main.print(person); } Person tom = new Person("X0000032", "Tom", "m", new Timestamp(System.currentTimeMillis())); // 更新 personMapper.update(tom); Person foundTom = personMapper.find("X0000032"); Main.print(foundTom); } private static void print(Person person) { System.out.println("ID " + person.getId()); System.out.println("name " + person.getName()); System.out.println("Sex " + person.getSex()); System.out.println("Update date " + person.getUpdatedate()); System.out.println(); } }
参考文献
http://d.hatena.ne.jp/asakichy/20120622/1340316281http://gihyo.jp/dev/serial/01/ruby/0014
http://capsctrl.que.jp/kdmsnr/wiki/PofEAA/?DataMapper
http://otndnld.oracle.co.jp/columns/arai-semi/data_access/2/
http://www.csus4.net/poeaa/PoEAA03_MappingRDB.pdf