Вопрос

Я хотел знать, что сообщество считает «лучшими практиками» в отношении картирования иерархий классов с Spring JDBC.

У нас нет возможности использовать полный инструмент ORM с полным бечным, однако мы используем Spring JDBC, чтобы облегчить некоторую утомительную природу JDBC. Одним из классов, который мы используем очень регулярно, является BeanPropertyRowMapper для его простоты использования и возможности иметь доступ к собственности с нечувствительным типом из нашего набора результатов.

У меня есть классная иерархия, которую все отображают обратно в одну таблицу (используя подход на таблицу за ход для этой маленькой иерархии классов). Таким образом, таблица содержит классический столбец, который можно использовать для определения того, какой класс фактически должен быть создан. Бывший. 1 = менеджер, 2 = сотрудник, 3 = подрядчик. Все это «люди», но у каждого подкласса человека есть несколько атрибутов, которые являются уникальными для их класса.

Моя первоначальная мысль состоит в том, чтобы создать подкласс BeanPropertyRowMapper и попытаться ввести эту логику, чтобы сказать «если столбец A = 1, тогда создайте экземпляр менеджера, а затем сделайте номинальное привязку».

Это кажется разумным подходом? Есть ли другие предложения, которые могут иметь у людей, которые сработали для вас?

Заранее спасибо за ваши ответы,

Джастин Н.

Это было полезно?

Решение

Не похоже, что в подклассе есть место, где вы можете добавить крючок, чтобы переключить класс, не полностью копируя реализацию MapRow () для BeanPropertyRowMapper. Ваш лучший подход может заключаться в создании класса Rowmapper, который делегирует соответствующую BeanPropertyRowmapper.

Например:

    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;

            }
        }
    };

Другие советы

Я не уверен, что это «лучшая практика», но я предлагаю следующий подход (без использования свойств бобов -> должен работать быстрее).

Обычно вы знаете, какой объект вы ожидаете получить. Таким образом, вы можете предоставить соответствующий карт строки при выполнении SQL.

Объявите пользовательский абстрактный общий rowmapper и создайте собственный карт строки для каждого типа человека, т.е.

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

По другому подходу вы можете объявить абстрактный метод в базовом Mapper для конкретного реквизита, т.е.

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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top