Создадим простое веб-приложение на Spring Boot 3 с доступом к базе через Hibernate и подключим его к СУБД PostgreSQL.
Инициализация проекта
Перейдите на сайт Spring Initializr. В левой части экрана в графе Project выберите Gradle (если не знаете, Groovy или Kotlin, то оставьте Groovy). В Project Metadata в графе Artifact введите название проекта. В данном примере будет использовать название spring-hibernate-postgresql. Это повлияет на некоторые автоматически сгенерированные классы.

Затем в правой части экрана нажмите кнопку ADD DEPENDENCIES…

В появившемся модальном окне выберите следующие зависимости (удерживайте ctrl при клике на пункт меню, чтобы не приходилось каждый раз снова открывать модальное окно):
- Spring Web
- Spring Data Jpa
- PostgreSQL Driver
Другие зависимости подключаем по собственному усмотрению. Возможно, что вы заходите сразу подключить Lombok. В рамках данного туториала мы ограничимся необходимым минимумом, чтобы не перегружать изложение.

Когда все зависимости выбраны, нажимаем внизу экрана кнопку GENERATE. Распаковываем скачанный архив и открываем папку spring-hibernate-postgresql (в данном примере) в среде разработки, например, в IntelliJ Idea.
Первый запуск приложения, проверка хибернейта и подключения к БД PostgreSQL.
В папке src/main/resources инициализатор создаст пустой файл application.properties. Заполним его следующим образом:
| 1 2 3 4 5 6 7 8 | spring.datasource.url=jdbc:postgresql://localhost/testdb spring.datasource.username=postgres spring.datasource.password=qwerty spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update server.port=8080 | 
Первые три строки особых пояснений не требуют. Через эти свойства мы передаём спрингу данные о подключении к СУБД: урл базы данных, имя пользователя и пароль. Если у вас в системе ещё не развёрнута СУБД PostgreSQL и не создана ни одна БД, то можете обратиться к этому туториалу.
Параметр spring.jpa.properties.hibernate.dialect сообщает спрингу, что хибернейт будет использовать для создания запросов соответствующий sql-диалект.
А параметр spring.jpa.hibernate.ddl-auto, установленный в значение update, заставит хибернейт при каждом запуске создавать/изменять таблицы в БД в соответствии с изменениями в классах предметной области. Добавим мы в класс новое поле, в таблице появится новая колонка и т.д.
Последний параметр server.port определяет, какой порт будет слушать встроенный сервер tomcat, в котором в итоге будет крутиться наше приложение.
Создадим класс предметной области:
| 1 2 3 4 5 6 7 8 9 10 | @Entity public class Person {     @Id     @GeneratedValue     private Long id;     private String name; //Конструкторы, геттеры и сеттеры, toString() и т.д. } | 
Самого добавления класса предметной области, помеченного аннотацией @jakarta.persistence.Entity, достаточно, чтобы хибернейт обнаружил его и создал ему соответствующую таблицу в БД (при условии, что мы выставили в настройках spring.jpa.hibernate.ddl-auto=update).
Чтобы в этом убедиться, давайте запустим наше приложение. Для этого можно поступить одним из двух способов:
Первый — открыть терминал в папке проекта и там выполнить команду
| 1 | ./gradlew bootRun | 

Второй — не заморачиваться и запустить проект на выполнение средствами IDE (здесь пример с IntelliJ Idea).

Теперь если мы подключимся с нашей БД через psql и проверим таблицу командой
| 1 | \d person | 
где person — это имя таблицы, то обнаружим, что такая таблица, во-первых, есть. А во-вторых, её структура соответствует тому, что мы написали в классе Person.

Если у вас psql выводит кракозябры вместо кириллицы, то это можно исправить.
Более детальное описание таблицы, можно получить сделав такой запрос:
| 1 | SELECT * FROM information_schema.columns WHERE table_name = 'person'; | 
Его, конечно, удобней делать в графическом режиме, например, в pgAdmin, который поставляется вместе с СУБД postgreSQL.

Создание основных бинов веб-приложения
Создадим бин репозитория для сущности Person:
| 1 2 3 | @Repository public interface PersonRepository extends JpaRepository<Person, Long> { } | 
Поскольку мы используем Spring data JPA, то репозиторий мы создаём в виде интерфейса, имплементацию Спринг создаст автоматически.
Затем создадим сервис:
| 1 2 3 4 5 6 7 8 9 10 | @Service public class PersonService {     @Autowired     PersonRepository personRepository;     public Person add(Person person) {         return personRepository.save(person);     } } | 
И наконец контроллер:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | @RestController @RequestMapping(path = "/person") public class PersonController {     @Autowired     PersonService personService;     @PostMapping("/add")     public ResponseEntity<Long> add(@RequestBody Person person) {         personService.add(person);         return ResponseEntity.ok(person.getId());     } } | 
Теперь мы можем снова запустить приложение и проверить работу контроллера, отправив POST запрос по адресу http://localhost:8080/person/add.
Сделать это можно следующей командой:
| 1 | curl -d '{"name":"Vladimir"}' -H "Content-type: application/json" -X POST http://localhost:8080/person/add | 

Команда curl, доступная через консоль PowerShell, работает совсем не так, как curl в *nix системах (в Windows это просто альяс для утилиты Invoke-WebRequest), поэтому выполнять эту команду нужно из Git Bash или чего-то подобного. Тогда всё должно отработать нормально.
Открыв консоль psql, можно убедиться, что запрос отработал корректно. Данные попали в контроллер, оттуда по цепочке в репозиторий, а затем Hibernate сохранил их в соответствующую таблицу в базе.

Написание тестового метода
Всё-таки проверять отдельные части приложения удобней, не запуская его, поэтому давайте напишем заготовку интеграционного теста. Инициализатор автоматически создал первый тестовый класс для приложения и разместил его в соответствующем пакете. В нашем случае класс называется SpringHibernatePostgresqlApplicationTests. Наполним его следующим содержанием:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | @SpringBootTest class SpringHibernatePostgresqlApplicationTests { 	@Autowired 	PersonRepository personRepository; 	@Autowired 	private WebApplicationContext wac; 	private MockMvc mockMvc; 	@BeforeEach 	void setup() { 		this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); 	} 	@Test 	void addNewPersonApi() throws Exception { 		Person irina = new Person("Irina"); 		String responseContent = mockMvc.perform(MockMvcRequestBuilders 						.post("/person/add") 						.contentType(MediaType.APPLICATION_JSON) 						.content(new ObjectMapper().writeValueAsString(irina))) 				.andExpect(status().isOk()) 				.andReturn().getResponse().getContentAsString(); 		Long irinaId = Long.valueOf(responseContent); 		Long dbEntryId = personRepository.findById(irinaId).map(Person::getId).orElseThrow(); 		assertEquals(irinaId, dbEntryId); 		personRepository.deleteById(irinaId); 	} } | 
Тест поднимет контекст Спринг-приложения, отправит POST запрос на наш контроллер и получит ответ с id сохранённой строки. Затем уже напрямую через бин репозитория извлечёт из БД строку по полученному id. И если в БД действительно окажется строка с таким же id, значит добавление прошло успешно. В конце мы удаляем тестовую строку из БД.
Создание исполняемого jar файла для дальнейшего развёртывания
Чтобы создать jar файл с нашим приложением, который можно было бы запустить командой java -jar appname.jar, нужно выполнить задачу bootJar в Gradle. Это можно сделать либо через терминал в папке проекта, набрав
| 1 | ./gradlew bootJar | 

Либо то же самое можно сделать, не выходя из IDE:

После выполнения этой задачи Gradle создаст в подпапке \build\libs проекта исполняемый джарник, который и можно будет запустить с помощью команды java -jar appname.jar.
Обратите внимание, что помимо bootJar в Gradle есть ещё задача jar. И она тоже создаёт джарник. Но его нельзя запустить. Он будет жаловаться на отсутствие манифеста. Может возникнуть желание погуглить проблему, создать так называемый толстый джарник (fat jar) и так далее и тому подобное.
Ничего этого делать не нужно. Для Spring Boot приложения в Gradle есть специальная задача (таска) по созданию джарника и это задача bootJar и, запустив её, мы получим нормальный исполняемый джарник с нашим приложением.