2009-12-02 12 views
5

Chciałem wiedzieć, co społeczność uważa za "najlepsze praktyki" w zakresie mapowania hierarchii klas za pomocą Spring JDBC.Spring JDBC RowMapper z klasami Hiearchie

Nie mamy możliwości korzystania z pełnowartościowego narzędzia ORM, jednak używamy Spring JDBC, aby złagodzić niektóre z nużącej natury JDBC. Jedną z klas, z której korzystamy bardzo regularnie, są BeanPropertyRowMapper ze względu na łatwość użytkowania i możliwość uzyskania niewrażliwego na typ obiektu dostępu do komponentu bean z naszego zestawu wyników.

Mam hierarchii klas, że wszystkie mapy z powrotem do jednej tabeli (biorąc podejście tabela na hiearchy dla tej małej hierarchii klasy). W związku z tym tabela zawiera kolumnę classId, której można użyć do określenia, która klasa powinna być faktycznie utworzona. Dawny. 1 = kierownik, 2 = pracownik, 3 = kontrahent. Wszystkie te są "Ludzie", ale każda podklasa osoby ma kilka atrybutów, które są unikalne dla ich klasy.

Moja początkowa myśl polega na utworzeniu podklasy BeanPropertyRowMapper i spróbuj wprowadzić tę logikę, aby powiedzieć "jeśli kolumna A = 1, a następnie stwórz managera, a następnie wykonaj wiązanie nomalne".

Czy wydaje się to rozsądnym podejściem? Czy są jakieś inne sugestie, które mogą mieć dla ciebie ludzie?

Dzięki z góry za odpowiedzi,

Justin N.

Odpowiedz

4

To nie wygląda jak tam jest miejsce na podklasy, gdzie można dodać hak przełączyć klasę bez całkowitego kopiowania realizację mapRow() dla BeanPropertyRowMapper. Najlepszym rozwiązaniem może być utworzenie klasy RowMapper, która deleguje do odpowiedniej BeanPropertyRowMapper.

Na przykład:

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

Dzięki za odpowiedź. Właśnie to zrobiłem! Dobrze, że uzyskałeś pewną walidację. – jnt30

1

nie jestem pewien, że to „najlepsze praktyki”, ale proponuję następujące podejście (bez użycia właściwości fasoli -> powinien działać szybciej).

Zazwyczaj wiesz, jakiego rodzaju obiektu spodziewasz się odzyskać. Możesz więc podać odpowiedni program odwzorowujący wiersze po uruchomieniu sql.

stwierdzenie zwyczaj Streszczenie ogólna RowMapper i stworzyć własny rząd mapowania dla każdego rodzaju osoby, tj:

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 
} 
} 

przez inne podejście można zadeklarować metody abstrakcyjne w bazowej odwzorowującym dla poszczególnych podpór, czyli

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; 
} 
Powiązane problemy