Поиск нескольких таблиц и возврат / отображение динамического набора результатов - PullRequest
1 голос
/ 28 ноября 2011

У меня есть схема mySql с именем Contacts, которая содержит 4 таблицы: контакты, телефон, электронная почта и адреса.Таблица контактов содержит основную информацию о человеке, такую ​​как идентификационный номер, имя и фамилия.Все остальные таблицы содержат внешний ключ, который связывает его с таблицей контактов, поэтому, например, Джон Доу в таблице контактов может иметь несколько телефонных номеров в таблице «Телефоны», которые можно искать по номеру идентификатора Джона Доу.

Мой вопрос заключается в том, как запросить эту схему и вернуть все данные для одного (или нескольких) пользователей.Может ли это быть сделано с одним оператором SQL, или мне нужно связаться с базой данных для каждой отдельной таблицы на основе того факта, что количество возвращаемых результатов не будет совпадать для каждой строки, возвращаемой из таблицы контактов.Например, у меня есть некоторые базовые функции поиска, которые ищут в таблице контактов одну или несколько строк на основе критериев поиска:

public class ContactsListDAO {
//Constants
private static final String SQL_FIND_BY_SEARCH_CRITERIA = "SELECT * FROM Contacts.Contacts WHERE Id LIKE :searchString OR FirstName LIKE :searchString OR LastName LIKE :searchString";

//Variables
private DAOFactory daoFactory;
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

//Constructors
public ContactsListDAO(DAOFactory daoFactory) {
    this.daoFactory = daoFactory;
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(daoFactory.getDataSource());
}

public List<Contact> findSearchResults(String searchCriteria) {
    Map<String, String> namedParameters = Collections.singletonMap("searchString", searchCriteria);

    RowMapper<Contact> mapper = new RowMapper<Contact>() {
        @Override
        public Contact mapRow(ResultSet resultSet, int row) throws SQLException {
            Contact contact = new Contact(
                    resultSet.getInt("Id"),
                    resultSet.getString("FirstName"),
                    resultSet.getString("LastName")
                );
            return contact;
        }           
    };

    return namedParameterJdbcTemplate.query(SQL_FIND_BY_SEARCH_CRITERIA, namedParameters, mapper);
}
}

Я использую Spring для запроса и отображения результатов обратно в бин Contact.Как бы я изменил этот оператор SQL и функциональность сопоставления для поиска в таблице контактов, получения данных для каждой строки и затем на основе идентификатора каждой возвращенной строки, а также для запроса таблиц телефона, электронной почты и адреса, а затем сопоставить их сСписок объектов, хранящихся в бине?Проблема состоит в том, что идентификатор строки 1 может найти 8 строк телефонных номеров, которые соответствуют идентификатору, но идентификатор строки 2 может найти только 3 телефонных номера.Как это будет храниться в ResultSet?Или мне нужно будет сначала запросить таблицу контактов, а затем выполнить отдельный запрос для каждой другой таблицы (для каждой строки, возвращаемой из первой) и добавить эти данные в бин в каждом конкретном случае?Если первый запрос возвращает 100 результатов, и мне нужно выполнить запрос для каждого из них по 3 таблицам, я просматриваю 301 поездку в базу данных и обратно.

Можно ли использовать один запрос и простовернуть 1 результат из каждой таблицы телефона, электронной почты, адреса для каждого результата, найденного в таблице контактов?Может быть, я могу добавить основной столбец или что-то еще, чтобы он возвращал только 1 результат, а затем, если пользователь щелкает что-то для запроса дополнительной информации о результате, он может выполнять другие запросы и собирать всю информацию об этом пользователе.

1 Ответ

0 голосов
/ 28 ноября 2011

Приведенный мной запрос использует LEFT JOIN для поиска в таблицах:

SELECT * FROM Contacts.Contacts LEFT JOIN Contacts.Phone ON Contacts.Id = Phone.ContactId AND Phone.Primary = 1 LEFT JOIN Contacts.Email ON Contacts.Id = Email.ContactId AND Email.Primary = 1 WHERE Contacts.Id LIKE :searchString OR Contacts.FirstName LIKE :searchString OR Contacts.LastName LIKE :searchString AND Contacts.OrganizationId = :organizationId

Я создал столбец в базе данных Phone, Email и Address с именем Primary, который содержит логическое значение, так чтомой первоначальный запрос я верну только 1 результат для каждого контакта в базе данных.Пока что это делает то, что мне нужно.Не уверен, что это правильный путь?

...