</dependency>
Вам также понадобится база данных, в которой будут храниться ваши данные. Для наших целей, встроенная база данных будет идеальна. Я предпочитаю встроенную базу данных H2, поэтому я добавил следующую зависимость в сборку:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Позже, вы увидите, как настроить приложение для использования внешней базы данных. Но сейчас, давайте перейдем к написанию репозитория, который извлекает и сохраняет данные Ingredient.
ОПРЕДЕЛЕНИЕ РЕПОЗИТОРИЕВ JDBC
Репозиторий Ingredient должен выполнять следующие операции:
Query запрос всех ингредиентов в коллекцию Ingredient объектов
Запрос одного Ingredient по его id
Сохранить объект Ingredient
Следующий интерфейс IngredientRepository определяет эти три операции объявляя методы:
package tacos.data;
import tacos.Ingredient;
public interface IngredientRepository {
Iterable<Ingredient> findAll();
Ingredient findOne(String id);
Ingredient save(Ingredient ingredient);
}
Несмотря на то, что интерфейс отражает суть того, что вам нужно сделать в репозитории ингредиентов, вам все равно нужно написать реализацию IngredientRepository, использующую JdbcTemplate для запроса к базе данных. Код, показанный далее, является первым шагом в написании этой реализации.
листинг 3.4 -Начало репозиторий ингредиент с JdbcTemplate
package tacos.data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import tacos.Ingredient;
@Repository
public class JdbcIngredientRepository implements IngredientRepository {
private JdbcTemplate jdbc;
@Autowired
public JdbcIngredientRepository(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
...
}
Как вы можете видеть, JdbcIngredientRepository аннотируется @Repository. Эта аннотация является одной из немногих аннотаций стереотипов, которые определяет Spring, включая @Controller и @Component. Аннотируя JdbcIngredientRepository с помощью @Repository, вы объявляете, что он должен быть автоматически обнаружен при сканировании компонентов Spring и создан как bean в контексте приложения Spring.
Когда Spring создает bean JdbcIngredientRepository, он внедряет JdbcTemplate через аннотированную конструкцию @Autowired. Конструктор назначает JdbcTemplate переменной экземпляра, которая будет использоваться в других методах для запроса и вставки в базу данных. Говоря об остальных методах, давайте взглянем на реализации findAll () и findById ().
Листинг 3.5 запросы к базе данных с JdbcTemplate
@Override
public Iterable<Ingredient> findAll() {
return jdbc.query("select id, name, type from Ingredient",
this::mapRowToIngredient);
}
@Override
public Ingredient findOne(String id) {
return jdbc.queryForObject(
"select id, name, type from Ingredient where id=?",
this::mapRowToIngredient, id);
}
private Ingredient mapRowToIngredient(ResultSet rs, int rowNum) throws QLException {
return new Ingredient(
rs.getString("id"),
rs.getString("name"),
Ingredient.Type.valueOf(rs.getString("type")));
}
findAll() и findById() используют JdbcTemplate аналогичным образом. Метод findAll(), ожидающий возврата коллекции объектов, использует JdbcTemplate метод запроса. Метод query() принимает SQL для запроса, а также реализацию Spring-овского RowMapper с целью сопоставления каждой строки в результирующем наборе объекту. findAll() также принимает в качестве окончательного аргумента (аргументов) список любых параметров, необходимых в запросе. Но, в данном случае, нет никаких обязательных параметров.
Метод findById() возвращает только один объект ингредиента, поэтому он использует метод queryForObject() JdbcTemplate вместо query(). queryForObject() работает так же, как query(), за исключением того, что возвращает один объект вместо списка объектов. В этом случае ему дается запрос для выполнения, RowMapper и id Ingredient для выборки, который используется вместо ? в запросе.
Как показано в листинге 3.5, параметр RowMapper для findAll() и findById() задается как ссылка на метод mapRowToIngredient(). Ссылки на методы Java 8 и лямбда-выражения удобны при работе с JdbcTemplate в качестве альтернативы явной реализации RowMapper. Но если по какой-то причине вы хотите или нуждаетесь в явном RowMapper, то следующая реализация findAll() показывает, как это сделать:
@Override
public Ingredient findOne(String id) {
return jdbc.queryForObject(
"select id, name, type from Ingredient where id=?",
new RowMapper<Ingredient>() {
public Ingredient mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Ingredient(
rs.getString("id"),
rs.getString("name"),
Ingredient.Type.valueOf(rs.getString("type")));
};
}, id);
}
Чтение данных из базы данных-это только часть истории. В какой-то момент данные должны быть записаны в базу данных, чтобы их можно было прочитать. Итак, давайте рассмотрим реализацию метода save().