2009-12-02 6 views
5

Ich wollte wissen, was die Community als "Best Practices" in Bezug auf das Zuordnen von Klassenhierarchien mit Spring JDBC betrachtet.Spring JDBC RowMapper mit Klasse Hierarchies

Wir haben nicht die Möglichkeit, ein vollwertiges ORM-Tool zu verwenden, jedoch verwenden wir die Spring-JDBC, um die langweilige Natur von JDBC zu verringern. Eine Klasse, die wir sehr regelmäßig nutzen, ist der BeanPropertyRowMapper für seine Benutzerfreundlichkeit und die Möglichkeit, von unserer Ergebnismenge aus Zugriff auf den Typ insensitive Bean-Eigenschaften zu erhalten.

Ich habe eine Klassenhierarchie, die alle Zuordnungen zurück zu einer einzigen Tabelle (unter Verwendung der Table-per-Hierarchy-Ansatz für diese kleine Klassenhierarchie). Daher enthält die Tabelle eine classId-Spalte, die verwendet werden kann, um zu bestimmen, welche Klasse tatsächlich instanziiert werden soll. Ex. 1 = Manager, 2 = Mitarbeiter, 3 = Auftragnehmer. Alle diese sind "Leute", aber jede Unterklasse von Person hat ein paar Attribute, die für ihre Klasse einzigartig sind.

Mein erster Gedanke ist es, eine Unterklasse von BeanPropertyRowMapper zu erstellen und diese Logik zu injizieren, um zu sagen: "Wenn Spalte A = 1 dann instanziiere einen Manager und mache dann deine Nominalbindung".

Scheint dies ein vernünftiger Ansatz? Gibt es noch andere Vorschläge, die Leute für Sie gemacht haben?

Vielen Dank im Voraus für Ihre Antworten,

Justin N.

Antwort

4

Es sieht nicht wie es in der Unterklasse ein Ort ist, wo man einen Haken hinzufügen könnte, die Klasse zu wechseln, ohne vollständig zu kopieren, die Umsetzung von mapRow() für BeanPropertyRowMapper. Der beste Ansatz könnte darin bestehen, eine RowMapper-Klasse zu erstellen, die an den entsprechenden BeanPropertyRowMapper delegiert.

Zum Beispiel:

final RowMapper managerMapper = new BeanPropertyRowMapper(Manager.class); 
    final RowMapper employeeMapper = new BeanPropertyRowMapper(Employee.class); 
    final RowMapper contractorMapper = new BeanPropertyRowMapper(Contractor.class); 

    RowMapper rm = new RowMapper() 
    { 
     @Override 
     public Object mapRow(ResultSet rs, int rowNum) 
      throws SQLException 
     { 
      int employeeType = rs.getInt("type"); 
      switch (employeeType) 
      { 
       case 1: 
        return managerMapper.mapRow(rs, rowNum); 

       case 2: 
        return employeeMapper.mapRow(rs, rowNum); 

       case 3: 
        return contractorMapper.mapRow(rs, rowNum); 

       default: 
        break; 

      } 
     } 
    }; 
+0

Danke für die Antwort. Das war es, was ich getan habe! Gut, um eine Bestätigung zu bekommen. – jnt30

1

Ich bin nicht sicher, dass es die ‚best practice‘, aber ich schlage vor, den folgenden Ansatz (ohne Bean-Eigenschaften mit -> soll schneller arbeiten).

Normalerweise wissen Sie, welche Art von Objekt Sie abrufen möchten. So können Sie den entsprechenden Zeilenmapper bereitstellen, wenn Sie die SQL ausführen.

deklarieren benutzerdefinierte abstrakte allgemeine RowMapper und eigene Reihe Mapper für jede Art von Person zu erstellen, das heißt:

private static abstract class PersonRowMapper<T extends Person> implements RowMapper<T> { 

@Override 
public abstract T mapRow(ResultSet rs, int rowNum) throws SQLException; 

protected void mapBase(ResultSet rs, T person) throws SQLException { 
    //base mapping here 
} 
} 


private static class EmployeeRowMapper extends PersonRowMapper<Employee> { 

@Override 
public Employee mapRow(ResultSet rs, int rowNum) throws SQLException { 
    Employee e = new Employee(); 
    mapBase(rs, e); 
    //set other specific employee props 
} 
} 

Mit anderen Ansatz können Sie abstrakte Methode in der Basis-Mapper für bestimmte Requisiten erklären, das heißt

private static abstract class PersonRowMapper<T extends Person> implements RowMapper<T> { 
@Override 
public T mapRow(ResultSet rs, int rowNum) throws SQLException { 
    T instance = getInstance(); 
    //set base props here 
    fill(rs, instance); 
} 

//e.g. return new Employee() 
protected abstract T getInstance(); 
//fill specific instance props 
protected abstract void fill(ResultSet rs, T instance) throws SQLException; 
} 
Verwandte Themen