Статьи

Как указать именованные параметры с помощью NamedParameterJdbcTemplate

обзор

Spring JdbcTemplate — это мощный механизм для подключения к базе данных и выполнения SQL-запросов. Он внутренне использует JDBC API, но устраняет множество проблем с JDBC API. Это помогает избежать написания стандартного кода, например, для создания соединения, оператора, закрытия набора результатов, соединения и т. Д. 

С JdbcTemple мы обычно передаем значения параметров с «?» (вопросительный знак). Тем не менее, это будет представлять проблему внедрения SQL. Итак, Spring предоставляет другой способ вставки данных по названному параметру. Таким образом, мы используем имена вместо «?». Так что лучше запомнить данные для столбца. Это можно сделать с помощью  NamedParameterJdbcTemplate .

В этой статье мы узнаем, как использовать  NamedParameterJdbcTemplate для передачи именованного параметра.

Предпосылки

  • JDK 1.8

  • Spring-Boot Базовые знания

  • Gradle

  • Любая IDE (Eclipse, VSD)

Gradle Dependency

Этот проект нуждается в стандартном spring-boot-starter-web вместе с spring-boot-starter-jdbc и драйвером базы данных h2 . Я использую весеннюю загрузку  springBootVersion = '2.1.2.RELEASE' для этого упражнения:

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

конфигурация

Мы используем H2 в качестве базы данных. И H2 предоставляет веб-интерфейс под названием H2 Console для просмотра данных. Давайте включим консоль h2 в application.properties

/src/main/resources/application.properties:

# Enabling H2 Console
spring.h2.console.enabled=true

server.port=8100

Кроме того, мы настроили порт как 8100 для этого приложения. Мы увидим, как использовать консоль H2 позже. А пока давайте добавим другой необходимый код.

Домен

Давайте создадим домен класса User . Мы будем использовать этот класс для сопоставления с таблицей БД USERS и вставки каждого поля этого объекта в эту таблицу:

public class User {

    private int id;
    private String name;
    private String address;
    private String email;
  // standard setters and getters
}

DAO

Теперь давайте создадим интерфейс DAO UserDao, который определяет, какие все методы должны быть реализованы:

public interface UserDao {
    public User create(final User user) ;
    public List<User> findAll() ;
    public User findUserById(int id);
}

DAOImpl

Теперь давайте создадим класс реализации. Это будет реализовывать все методы UserDao . Здесь мы будем использовать  NamedParameterJdbcTemplate для создания и извлечения записи. NamedParameterJdbcTemplate имеет много методов. Мы использовали 3 метода, чтобы продемонстрировать, как передавать именованные параметры:

@Repository
public class UserDaoImpl implements UserDao {

private final String INSERT_SQL = "INSERT INTO USERS(name, address, email)  values(:name,:address,:email)";
private final String FETCH_SQL = "select record_id, name, address, email from users";
private final String FETCH_SQL_BY_ID = "select * from users where record_id = :id";

@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public User create(final User user) {
KeyHolder holder = new GeneratedKeyHolder();
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("name", user.getName())
.addValue("address", user.getAddress())
.addValue("email", user.getEmail());
namedParameterJdbcTemplate.update(INSERT_SQL, parameters, holder);
user.setId(holder.getKey().intValue());
return user;
}

public List<User> findAll() {
return namedParameterJdbcTemplate.query(FETCH_SQL, new UserMapper());
}

public User findUserById(int id) {
Map<String, Integer> parameters = new HashMap<String, Integer>();
parameters.put("id", id);
return (User) namedParameterJdbcTemplate.queryForObject(FETCH_SQL_BY_ID, parameters, new UserMapper());
}

}

class UserMapper implements RowMapper {

@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("record_id"));
user.setName(rs.getString("name"));
user.setAddress(rs.getString("address"));
user.setEmail(rs.getString("email"));
return user;
}

}

1. update ()  — мы использовали метод update ()  для вставки данных в  таблицу USERS . Если мы использовали обычный JDBCTemplate, мы будем использовать

Строка INSERT_SQL  = «INSERT INTO USERS(name, address, email) values (?,?,?)"; 

Но мы использовали NamedParameterJdbcTemplate, поэтому наша строка запроса будет выглядеть следующим образом:   мы видим, что мы используем именованные параметры вместо «?».    INSERT_SQL = "INSERT INTO USERS(name, address, email)values(:name,:address,:email)";

2. query () — мы использовали метод query () для извлечения всех записей пользователя из таблицы USERS . Здесь наша строка запроса будет:   String FETCH_SQL = "select record_id, name, address, email from users";  

Это будет так же, как любой другой запрос jdbcTemplate. Никакой специальной обработки здесь.

3. queryForObject () — Мы использовали  метод queryForObject () для извлечения пользователя на основе поля record_id. Здесь у нас будет строка запроса, как показано ниже:

 String FETCH_SQL_BY_ID = "select * from users where record_id = :id"; 
Если вы заметили, здесь мы использовали именованный параметр « id » вместо «?».

Также обратите внимание, что мы использовали RowMapper для сопоставления набора результатов с объектом User.

контроллер

Теперь давайте быстро представим эту функциональность через REST, чтобы мы могли ее легко протестировать:

@RestController
public class UserController {
    @Autowired
    private UserDaoImpl userDao;

    @PostMapping("/users")
    public ResponseEntity<User> createUser() {
        User user   =   userDao.create(getUser());
        return ResponseEntity.ok(user);
    }

    @GetMapping("/users")
    public List<User> retrieveAllUsers() {
        return userDao.findAll();

    }
    @GetMapping("/users/{id}")
    public User retrieveUserById(@PathVariable int id ) {
        return userDao.findUserById(id);
    }

    private User getUser() {
User user = new User();
user.setAddress("Marathahalli, Bangalore");
user.setEmail("rajesh.bhojwani@gmail.com");
user.setName("Rajesh Bhojwani");
return user;
}

}

Сборка и тестирование

Чтобы построить это приложение, нам нужно запустить команду сборки Gradle:

 gradlew clean build 

Это сгенерирует файл jar в build / libs.

Чтобы запустить приложение, нам нужно запустить команду:   java -jar build/libs/springbootjdbc-0.0.1-SNAPSHOT.jar 

Теперь, перед тестированием приложения, нам нужно создать таблицу USERS в базе данных h2 . Итак, давайте запустим h2-console по адресу  http: // localhost: 8100 / h2-console. 

Убедитесь, что URL JDBC обновлен до  jdbc: h2: mem: testdb. И затем нажмите на кнопку Подключить . Теперь мы можем создать схему таблицы USERS , запустив оператор ddl.

 CREATE TABLE users (record_id bigint NOT NULL AUTO_INCREMENT, name varchar(100), address varchar(250), email varchar(100), PRIMARY KEY (record_id)); После того, как таблица создана, теперь мы можем протестировать наши REST API для создания и получения пользовательской записи.

1. POST call —   http://localhost:8100/users  

2. ПОЛУЧИТЬ звонок —    http://localhost:8100/users 

3. GET Call —   http://localhost:8100/users/1 

Заключение

Подводя итог, мы увидели в этой статье, как передавать именованные параметры с помощью  NamedParameterJdbcTemplate. 

Как обычно, код можно найти на Github .