В этой статье мы рассмотрим шаги по настройке приложения Spring Boot с PostgreSQL. У нас будет простая операция CRUD в базе данных Postgres, представив приложение через Rest API. Мы будем использовать POSTMAN для тестирования приложения.
Настройка Postgres Server
- Загрузите сервер Postgres по ссылке: https://www.postgresql.org/download/
- Запустите установщик. Он также спросит пароль для суперпользователя: postgres
- Нажмите на pgAdmin4.exe, расположенный в папке PostgreSQL внутри Program Files.
Настройка Spring Boot Application
Необходимое условие:
Установлен ли JDK 1.8?
- Загрузите пример проекта Spring Boot с https://start.spring.io/
- Обновите файл pom.xml, как показано ниже:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.sample</groupId>
<artifactId>postgress</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>postgress</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
spring-boot-starter-jdbc
артефакт даст все jar jbc связанные с весной банки
org.postgresql.postgresql
будет зависеть от драйвера postgres jdbc во время выполнения.
- Создайте schema.sql в папке ресурсов. Таблица сотрудника будет создана при запуске сервера. Это можно игнорировать, если вы не хотите, чтобы исходная база данных была настроена во время запуска сервера. Как правило, для создания готового к работе приложения этот шаг можно игнорировать, поскольку таблицы будут создаваться с помощью сценария непосредственно в БД.
CREATE TABLE employee
(
employeeName varchar(100) NOT NULL,
employeeId varchar(11) NOT NULL ,
employeeAddress varchar(100) DEFAULT NULL,
employeeEmail varchar(100) DEFAULT NULL,
PRIMARY KEY (employeeId)
);
- Создайте data.sql в папке ресурсов для загрузки первого набора сотрудников во время запуска. Иначе можно пропустить:
insert into employee(employeeId, employeeName , employeeAddress,employeeEmail) values('1','Jack','USA','[email protected]');
- Изменения в application.properties для настройки источника данных с URL, именем пользователя и паролем БД Postgres. 5432 порт по умолчанию Postgres. Hibernate автоматически выберет postgressSQLDialect.
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=admin
spring.datasource.initialization-mode=always
spring.datasource.initialize=true
spring.datasource.schema=classpath:/schema.sql
spring.datasource.continue-on-error=true
spring.jpa.hibernate.ddl-auto
отключит автоматическое создание таблиц в спящем режиме из объектов-сущностей. Обычно Hibernate запускает его, если определен объект. Но мы будем использовать собственный SQL-запрос с JdbcTemplate, поэтому мы можем отключить это, поскольку не будем создавать Entity.
spring.datasource.initialization-mode
помечен как всегда, поскольку мы хотим, чтобы инициализация базы данных происходила при каждом запуске. Это необязательно и сделано для этой цели.
spring.datasource.initialize=true
отметит инициализацию как истинную.
spring.datasource.continue-on-error=true
продолжит запуск приложения, несмотря на любые ошибки при инициализации данных.
spring.datasource.schema
путь к схеме, который необходимо инициализировать.
spring.datasource.url
URL БД Postgres. Это может быть и удаленная БД.
spring.datasource.username
имя пользователя для базы данных.
spring.datasource.password
пароль для базы данных.
- Создайте интерфейс dao и реализацию dao.
package com.sample.postgress.dao;
import java.util.List;
import com.sample.postgress.entity.Employee;
public interface EmployeeDao {
List<Employee> findAll();
void insertEmployee(Employee emp);
void updateEmployee(Employee emp);
void executeUpdateEmployee(Employee emp);
public void deleteEmployee(Employee emp);
}
package com.sample.postgress.dao;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import com.sample.postgress.entity.Employee;
import com.sample.postgress.mapper.EmployeeRowMapper;
@Repository
public class EmployeeDaoImpl implements EmployeeDao{
public EmployeeDaoImpl(NamedParameterJdbcTemplate template) {
this.template = template;
}
NamedParameterJdbcTemplate template;
@Override
public List<Employee> findAll() {
return template.query("select * from employee", new EmployeeRowMapper());
}
@Override
public void insertEmployee(Employee emp) {
final String sql = "insert into employee(employeeId, employeeName , employeeAddress,employeeEmail) values(:employeeId,:employeeName,:employeeEmail,:employeeAddress)";
KeyHolder holder = new GeneratedKeyHolder();
SqlParameterSource param = new MapSqlParameterSource()
.addValue("employeeId", emp.getEmployeeId())
.addValue("employeeName", emp.getEmployeeName())
.addValue("employeeEmail", emp.getEmployeeEmail())
.addValue("employeeAddress", emp.getEmployeeAddress());
template.update(sql,param, holder);
}
@Override
public void updateEmployee(Employee emp) {
final String sql = "update employee set employeeName=:employeeName, employeeAddress=:employeeAddress, employeeEmail=:employeeEmail where employeeId=:employeeId";
KeyHolder holder = new GeneratedKeyHolder();
SqlParameterSource param = new MapSqlParameterSource()
.addValue("employeeId", emp.getEmployeeId())
.addValue("employeeName", emp.getEmployeeName())
.addValue("employeeEmail", emp.getEmployeeEmail())
.addValue("employeeAddress", emp.getEmployeeAddress());
template.update(sql,param, holder);
}
@Override
public void executeUpdateEmployee(Employee emp) {
final String sql = "update employee set employeeName=:employeeName, employeeAddress=:employeeAddress, employeeEmail=:employeeEmail where employeeId=:employeeId";
Map<String,Object> map=new HashMap<String,Object>();
map.put("employeeId", emp.getEmployeeId());
map.put("employeeName", emp.getEmployeeName());
map.put("employeeEmail", emp.getEmployeeEmail());
map.put("employeeAddress", emp.getEmployeeAddress());
template.execute(sql,map,new PreparedStatementCallback<Object>() {
@Override
public Object doInPreparedStatement(PreparedStatement ps)
throws SQLException, DataAccessException {
return ps.executeUpdate();
}
});
}
@Override
public void deleteEmployee(Employee emp) {
final String sql = "delete from employee where employeeId=:employeeId";
Map<String,Object> map=new HashMap<String,Object>();
map.put("employeeId", emp.getEmployeeId());
template.execute(sql,map,new PreparedStatementCallback<Object>() {
@Override
public Object doInPreparedStatement(PreparedStatement ps)
throws SQLException, DataAccessException {
return ps.executeUpdate();
}
});
}
}
-
findAll () извлекает всех сотрудников, а затем сопоставляет набор результатов с объектом Employee, используя RowMapper, описанный ниже.
-
insertEmployee () вставит сотрудника, используя,
template.update(sql,param, holder)
где param — SqlParameterSource, который будет динамически отображать значения в запросе, отмеченном двоеточием. GeneratedKeyHolder вернет автоматически сгенерированное значение при вставке данных. -
executeUpdateEmployee () обновит сотрудника, используя
template.execute
template.execute(sql,map,new PreparedStatementCallback<Object>() {
@Override
public Object doInPreparedStatement(PreparedStatement ps)
throws SQLException, DataAccessException {
return ps.executeUpdate();
}
});
- EmployeeRowMapper для сопоставления результирующего набора, полученного из запроса выбора, с POJO.
package com.sample.postgress.mapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.sample.postgress.entity.Employee;
public class EmployeeRowMapper implements RowMapper<Employee> {
@Override
public Employee mapRow(ResultSet rs, int arg1) throws SQLException {
Employee emp = new Employee();
emp.setEmployeeId(rs.getString("employeeId"));
emp.setEmployeeName(rs.getString("employeeName"));
emp.setEmployeeEmail(rs.getString("employeeEmail"));
return emp;
}
}
- Вы можете создать контроллер и класс обслуживания следующим образом:
package com.sample.postgress.controller;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sample.postgress.entity.Employee;
import com.sample.postgress.service.EmployeeService;
@RestController
@RequestMapping("/postgressApp")
public class ApplicationController {
@Resource
EmployeeService employeeService;
@GetMapping(value = "/employeeList")
public List<Employee> getEmployees() {
return employeeService.findAll();
}
@PostMapping(value = "/createEmp")
public void createEmployee(@RequestBody Employee emp) {
employeeService.insertEmployee(emp);
}
@PutMapping(value = "/updateEmp")
public void updateEmployee(@RequestBody Employee emp) {
employeeService.updateEmployee(emp);
}
@PutMapping(value = "/executeUpdateEmp")
public void executeUpdateEmployee(@RequestBody Employee emp) {
employeeService.executeUpdateEmployee(emp);
}
@DeleteMapping(value = "/deleteEmpById")
public void deleteEmployee(@RequestBody Employee emp) {
employeeService.deleteEmployee(emp);
}
}
Теперь давайте использовать POSTMAN для проверки изменений:
Тест 1: Получить список сотрудников
HTTP: // локальный: 8080 / postgressApp / employeeList
Тест 2: Создать сотрудника
HTTP: // локальный: 8080 / postgressApp / createEmp
Мы видим запись, вставленную с Джонсом.
Тест 3: Обновление сотрудника
HTTP: // локальный: 8080 / postgressApp / executeUpdateEmp
Тест 4: Удалить сотрудника
HTTP: // локальный: 8080 / postgressApp / deleteEmpById
Заключение
Мы узнали, как настроить приложение Spring Boot с Postgres и как выполнить операцию CRUD. Вы найдете полный код здесь .
Удачного кодирования!