Pregunta

Quería saber qué considera la comunidad las "mejores prácticas" con respecto a las jerarquías de clase de mapeo con Spring JDBC.

No tenemos la capacidad de usar una herramienta ORM completa, sin embargo, estamos utilizando el Spring JDBC para aliviar parte de la naturaleza tediosa de JDBC. Una clase que aprovechamos muy regularmente es el beanpropertyrowmapper para su facilidad de uso y la capacidad de tener acceso a la propiedad de frijol insensible desde nuestro conjunto de resultados.

Tengo una jerarquía de clases que se remonta a una sola tabla (tomando el enfoque de mesa por diaminación para esta pequeña jerarquía de clase). Como tal, la tabla contiene una columna ClassID que puede usarse para determinar qué clase debe ser instanciada realmente. Ex. 1 = gerente, 2 = empleado, 3 = contratista. Todas estas son "personas", pero cada subclase de persona tiene algunos atributos que son exclusivos de su clase.

Mi pensamiento inicial es crear una subclase de BeanPropertyRowMapper e intentar inyectar esta lógica para decir "si la columna A = 1 luego instanciar un administrador y luego hacer su enlace nomral".

¿Parece esto un enfoque razonable? ¿Hay alguna otra sugerencia que la gente pueda tener que hayan funcionado para usted?

Gracias de antemano por sus respuestas,

Justin N.

¿Fue útil?

Solución

No parece que haya un lugar en la subclase donde podría agregar un gancho para cambiar la clase sin copiar completamente la implementación de Maprow () para BeanPropertyRowMapper. Su mejor enfoque podría ser crear una clase de RowMapper que delegue al beanpropertyrowmapper apropiado.

Por ejemplo:

    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;

            }
        }
    };

Otros consejos

No estoy seguro de que sea la 'mejor práctica', pero sugiero el siguiente enfoque (sin usar propiedades de frijoles -> debería funcionar más rápido).

Por lo general, sabes qué tipo de objeto espera recuperar. Por lo tanto, puede proporcionar un mapeador de fila correspondiente cuando ejecute el SQL.

Declare a RowMapper genérico abstracto personalizado y cree un mapeador de fila propio para cada tipo de persona, es decir:

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

Por otro enfoque, puede declarar el método abstracto en el mapeador base para accesorios específicos, es decir

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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top