サイトアイコン 知的好奇心

Spring Bootでデータベース(PostgreSQL)にアクセスする方法

Spring Bootでデータベース(PostgreSQL)にアクセスする方法をご紹介します。

条件

事前準備1

データベース作成

まずは、PostgreSQLにデータベースおよびテーブルを作成します。

以下のコマンドを実行します。

# create database testdb;

作成したデータベースへ切り替え

以下のコマンドで、作成したデータベースに切り替えます。

# \c testdb

テーブル作成

例として以下のようなテーブルを作成します。

create table weather (
    id              serial   primary key,   -- ID
    location_id     int,                    -- 地名ID
    name            varchar(20),            -- 地名
    temperature     int,                    -- 気温
    humidity        int,                    -- 湿度
    date_time       timestamp               -- 日時
);

データ追加

テーブルにデータを追加します。

insert into weather (location_id, name, temperature, humidity, date_time) values 
   (1, '東京', 15, 55, '2019-04-10 09:00:00'),
   (1, '東京', 16, 53, '2019-04-10 10:00:00'),
   (1, '東京', 17, 40, '2019-04-10 11:00:00'),
   (2, '那覇', 20, 65, '2019-04-10 09:00:00'),
   (2, '那覇', 22, 67, '2019-04-10 10:00:00'),
   (2, '那覇', 25, 69, '2019-04-10 11:00:00');

事前準備2

Spring Bootで適当なプロジェクトを作成します。

ここでは、単純な「Hello Worldプロジェクト」を使用します。

Hello Worldプロジェクトの作成については、以下の記事をご参照ください。

Spring BootでHello World

DB接続

DB接続情報の設定

application.propertiesに以下のような記述を追記します。(環境に応じて適宜変更してください。)

spring.jpa.database=POSTGRESQL
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=postgrespassword

依存関係

pom.xmlに以下の記述を追記します。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
	<groupId>org.postgresql</groupId>
	<artifactId>postgresql</artifactId>
	<scope>runtime</scope>
</dependency>

エンティティ作成

modelフォルダ配下に「Weather.java」を作成します。

package com.example.demo.model;

import java.sql.Timestamp;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="weather")
public class Weather {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    
    private Integer location_id;
    
    private String name;
    
    private Integer temperature;
    
    private Integer humidity;
    
    private Timestamp date_time;
    
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Integer getLocation_id() {
		return location_id;
	}

	public void setLocation_id(Integer location_id) {
		this.location_id = location_id;
	}
    
        public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getTemperature() {
		return temperature;
	}

	public void setTemperature(Integer temperature) {
		this.temperature = temperature;
	}

	public Integer getHumidity() {
		return humidity;
	}

	public void setHumidity(Integer humidity) {
		this.humidity = humidity;
	}

	public Timestamp getDate_time() {
		return date_time;
	}

	public void setDate_time(Timestamp date_time) {
		this.date_time = date_time;
	}   
}

リポジトリクラス作成

repositoryフォルダ配下に「WeatherRepository.java」を作成します。

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.demo.model.Weather;

@Repository
public interface WeatherRepository extends JpaRepository<Weather, Integer> {}

サービスクラス作成

serviceフォルダ配下に「WeatherService.java」を作成します。

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.demo.model.Weather;
import com.example.demo.repository.WeatherRepository;

@Service
@Transactional
public class WeatherService{
	
	@Autowired
	WeatherRepository weatherRepository;
	
	/**
	 * レコードを全件取得する。
	 * @return
	 */
	public List<Weather> findAllWeatherData(){
		
		return weatherRepository.findAll();
	}
}

コントローラの編集

「HelloController.java」を以下のように編集します。

package com.example.demo;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.demo.model.Weather;
import com.example.demo.service.WeatherService;

@Controller
public class HelloController {
	@Autowired
	WeatherService weatherService;
	
	@RequestMapping("/hello")
	public String hello(Model model) {
		
		model.addAttribute("hello", "Hello World!"); // Hello World!の表示
		
		// 気象データの取得
		List<Weather> weatherDataList = weatherService.findAllWeatherData();
		model.addAttribute("weatherDataList", weatherDataList);
		
		return "hello";
	}
}

テンプレートの編集

「hello.html」を以下のように編集します。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8" />
	<title></title>
</head>
<body>
<p>
	<span th:text="${hello}">Hello World!</span>
</p>

	<table>
		<tr th:each="data : ${weatherDataList}" th:object="${data}">
			<td th:text="*{id}"></td>
			<td th:text="*{location_id}"></td>
			<td th:text="*{name}"></td>
			<td th:text="*{temperature}"></td>
			<td th:text="*{humidity}"></td>
			<td th:text="*{date_time}"></td>
		</tr>
	</table>
</body>
</html>

エラー抑制

サーバー起動時に以下のようなエラーが出力されます。

java.lang.reflect.InvocationTargetException: null
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
	at org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl.useContextualLobCreation(LobCreatorBuilderImpl.java:113) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl.makeLobCreatorBuilder(LobCreatorBuilderImpl.java:54) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.<init>(JdbcEnvironmentImpl.java:271) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:114) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:94) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:179) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:119) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) ~[spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE]
	at com.example.demo.HelloApplication.main(HelloApplication.java:10) ~[classes/:na]
Caused by: java.sql.SQLFeatureNotSupportedException: org.postgresql.jdbc.PgConnection.createClob() メソッドはまだ実装されていません。
	at org.postgresql.Driver.notImplemented(Driver.java:688) ~[postgresql-42.2.5.jar:42.2.5]
	at org.postgresql.jdbc.PgConnection.createClob(PgConnection.java:1269) ~[postgresql-42.2.5.jar:42.2.5]
	... 44 common frames omitted

動作上、特に問題はなさそうですが、気になるので抑制します。

「hibernate.properties」を作成し、以下のように記述します。
(application.propertiesと同じフォルダに作成します。)

hibernate.jdbc.lob.non_contextual_creation = true

構成

ここまでの対応でソースは以下のような構成になりました。

実行結果

以下のようにレコード一覧が表示されます。

改造

すこし改造してみます。

application.properties

以下を追記します。

spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

それぞれ以下のような設定です。

1. エンティティの設計が実際のカラムと矛盾していないかチェックする。
2. SQLがログにフォーマットされた形で(見やすい形)で出力される。
3,4. SQLおよびSQLのバインドパラメータがログに出力されるよう設定する。

リポジトリ

「WeatherRepository.java」を以下のように修正します。

package com.example.demo.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.demo.model.Weather;

@Repository
public interface WeatherRepository extends JpaRepository<Weather, Integer> {
	
	List<Weather> findByName(String name);
}

サービス

「WeatherService.java」を以下のように修正します。

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.demo.model.Weather;
import com.example.demo.repository.WeatherRepository;

@Service
@Transactional
public class WeatherService{
	
	@Autowired
	WeatherRepository weatherRepository;
	
	/**
	 * レコードを全件取得する。
	 * @return
	 */
	public List<Weather> findAllWeatherData(){
		
		return weatherRepository.findAll();
	}
	
	/**
	 * 指定した都市のレコードを取得する。
	 * @param name
	 * @return
	 */
	public List<Weather> findWetherDataListByName(String name){
				
		return weatherRepository.findByName(name);
	}
}

コントローラ

「HelloController.java」を以下のように修正します。

package com.example.demo;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.demo.model.Weather;
import com.example.demo.service.WeatherService;

@Controller
public class HelloController {
	@Autowired
	WeatherService weatherService;
	
	@RequestMapping("/hello")
	public String hello(Model model) {
		
		model.addAttribute("hello", "Hello World!"); // Hello World!の表示
		
		// 気象データの取得
		List<Weather> weatherDataList = weatherService.findAllWeatherData();
		model.addAttribute("weatherDataList", weatherDataList);
        
		List<Weather> weatherDataTokyo = weatherService.findWetherDataListByName("東京");
		model.addAttribute("weatherDataTokyo", weatherDataTokyo);
        
		List<Weather> weatherDataNaha = weatherService.findWetherDataListByName("那覇");
		model.addAttribute("weatherDataNaha", weatherDataNaha);
 		
		return "hello";
	}
}

テンプレート

「Hello.html」を以下のように修正します。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8" />
	<title></title>
</head>
<body>
<p>
	<span th:text="${hello}">Hello World!</span>
</p>

	<table>
		<tr th:each="data : ${weatherDataList}" th:object="${data}">
			<td th:text="*{id}"></td>
			<td th:text="*{location_id}"></td>
			<td th:text="*{name}"></td>
			<td th:text="*{temperature}"></td>
			<td th:text="*{humidity}"></td>
			<td th:text="*{date_time}"></td>
		</tr>
	</table>
	
	<p>東京のデータ</p>
	<table>
		<tr th:each="data : ${weatherDataTokyo}" th:object="${data}">
			<td th:text="*{id}"></td>
			<td th:text="*{location_id}"></td>
			<td th:text="*{name}"></td>
			<td th:text="*{temperature}"></td>
			<td th:text="*{humidity}"></td>
			<td th:text="*{date_time}"></td>
		</tr>
	</table>
	
	<p>那覇のデータ</p>
	<table>
		<tr th:each="data : ${weatherDataNaha}" th:object="${data}">
			<td th:text="*{id}"></td>
			<td th:text="*{location_id}"></td>
			<td th:text="*{name}"></td>
			<td th:text="*{temperature}"></td>
			<td th:text="*{humidity}"></td>
			<td th:text="*{date_time}"></td>
		</tr>
	</table>
</body>
</html>

改造後の実行結果

以下のように表示されます。

改造後のログ出力

以下のようなSQLログが出力されます。

2019-04-20 20:59:44.542 DEBUG 2816 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        weather0_.id as id1_0_,
        weather0_.date_time as date_tim2_0_,
        weather0_.humidity as humidity3_0_,
        weather0_.location_id as location4_0_,
        weather0_.name as name5_0_,
        weather0_.temperature as temperat6_0_ 
    from
        weather weather0_
2019-04-20 20:59:44.581 DEBUG 2816 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        weather0_.id as id1_0_,
        weather0_.date_time as date_tim2_0_,
        weather0_.humidity as humidity3_0_,
        weather0_.location_id as location4_0_,
        weather0_.name as name5_0_,
        weather0_.temperature as temperat6_0_ 
    from
        weather weather0_ 
    where
        weather0_.name=?
2019-04-20 20:59:44.584 TRACE 2816 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [東京]
2019-04-20 20:59:44.589 DEBUG 2816 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        weather0_.id as id1_0_,
        weather0_.date_time as date_tim2_0_,
        weather0_.humidity as humidity3_0_,
        weather0_.location_id as location4_0_,
        weather0_.name as name5_0_,
        weather0_.temperature as temperat6_0_ 
    from
        weather weather0_ 
    where
        weather0_.name=?
2019-04-20 20:59:44.589 TRACE 2816 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [那覇]

JDBC

もちろん、JDBCも使用できます。

pom.xml

以下の記述を追記します。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

コントローラ

「HelloController.java」にJDBC関連処理を記述します。

package com.example.demo;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.demo.model.Weather;
import com.example.demo.service.WeatherService;

@Controller
public class HelloController {
	@Autowired
	WeatherService weatherService;
	
	@Autowired
	JdbcTemplate jdbcTemplate;
	
	@RequestMapping("/hello")
	public String hello(Model model) {
		
		model.addAttribute("hello", "Hello World!"); // Hello World!の表示
		
		// 気象データの取得
		List<Weather> weatherDataList = weatherService.findAllWeatherData();
 		model.addAttribute("weatherDataList", weatherDataList);
        
 		List<Weather> weatherDataTokyo = weatherService.findWetherDataListByName("東京");
 		model.addAttribute("weatherDataTokyo", weatherDataTokyo);
        
 		List<Weather> weatherDataNaha = weatherService.findWetherDataListByName("那覇");
 		model.addAttribute("weatherDataNaha", weatherDataNaha);
 		
		// JDBC
		System.out.println("*** JDBC Start. ***");
		String sql = "select * from weather";
		List<Map<String, Object>> sqlResultList = jdbcTemplate.queryForList(sql);
		sqlResultList.forEach(s -> {
				System.out.println(s);
		});
		System.out.println("*** JDBC End. ***");
        
		return "hello";
	}
}

実行結果

以下のように出力されます。

*** JDBC Start. ***
{id=1, location_id=1, name=東京, temperature=15, humidity=55, date_time=2019-04-10 09:00:00.0}
{id=2, location_id=1, name=東京, temperature=16, humidity=53, date_time=2019-04-10 10:00:00.0}
{id=3, location_id=1, name=東京, temperature=17, humidity=40, date_time=2019-04-10 11:00:00.0}
{id=4, location_id=2, name=那覇, temperature=20, humidity=65, date_time=2019-04-10 09:00:00.0}
{id=5, location_id=2, name=那覇, temperature=22, humidity=67, date_time=2019-04-10 10:00:00.0}
{id=6, location_id=2, name=那覇, temperature=25, humidity=69, date_time=2019-04-10 11:00:00.0}
*** JDBC End. ***

参考

Qiita:SpringBoot + Spring JPAでデータベースに接続する

https://qiita.com/t-iguchi/items/685c0a1bb9b0e8ec68d2

Qiita:HibernateでPostgreSQLに接続する際の初期化時エラー

https://qiita.com/bwtakacy/items/be3509e1765546f92184

Spring徹底入門

モバイルバージョンを終了