Pergunta

Eu queria saber o que a comunidade considera as "melhores práticas" em relação ao mapeamento de hierarquias da classe com o Spring JDBC.

Não temos a capacidade de usar uma ferramenta ORM completa, no entanto, estamos usando o JDBC da mola para aliviar parte da natureza tediosa do JDBC. Uma classe que aproveitamos regularmente é o BeanPropertyRowmapper para a facilidade de uso e a capacidade de ter acesso à propriedade de feijão insensível do nosso conjunto de resultados.

Eu tenho uma hierarquia de classes que todos os mapas de volta para uma única tabela (adotando a abordagem de mesa por pesquisa para essa hierarquia de classe pequena). Como tal, a tabela contém uma coluna ClassID que pode ser usada para determinar qual classe deve realmente ser instanciada. Ex. 1 = gerente, 2 = funcionário, 3 = contratado. Tudo isso são "pessoas", mas cada subclasse da pessoa tem alguns atributos exclusivos da sua classe.

Meu pensamento inicial é criar uma subclasse do BeanPropertyRowmapper e tentar injetar essa lógica para dizer "Se a coluna A = 1, instanciar um gerente e, em seguida, fazer sua ligação nomral".

Isso parece uma abordagem razoável? Existem outras sugestões que as pessoas podem ter que funcionaram para você?

Agradecemos antecipadamente por suas respostas,

Justin N.

Foi útil?

Solução

Não parece que há um lugar na subclasse onde você possa adicionar um gancho para mudar a classe sem copiar completamente a implementação do maprow () para o BeanPropertyRowmapper. Sua melhor abordagem pode ser criar uma classe Rowmapper que delega ao BeanPropertyRowmapper apropriado.

Por exemplo:

    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;

            }
        }
    };

Outras dicas

Não tenho certeza se é a 'prática recomendada', mas sugiro a seguinte abordagem (sem usar as propriedades do feijão -> deve funcionar mais rapidamente).

Geralmente você sabe que tipo de objeto você espera recuperar. Para que você possa fornecer mapeador de linha correspondente ao executar o SQL.

Declare o Rowmapper genérico abstrato personalizado e crie o seu próprio mapeador de linha para cada tipo de pessoa, ou seja::

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 outra abordagem, você pode declarar o método abstrato no mapeador básico para adereços específicos, ou seja,

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top