本篇說明如何建立Spring Boot 2,Spring Data JPA對MySQL進行基本操作的專案。
首先安裝STS(Spring Tool Suite)或在Eclipse安裝STS plugin。
然後電腦中要安裝好MySQL資料庫(本範例安裝版本為8.0.11),啟動,並建立一個mydb
資料庫(schema)。
接著建立一個Spring Boot專案,在Eclipse功能選單選擇 File -> New -> Spring Starter Project
。
將專案Maven資訊填寫如下後按Next >。
在SQL項下找到JPA,勾選後按Finish。
預設的pom.xml
內容如下,(如果你的pom.xml
第一行有出現未知的錯誤,請參考Eclipse Maven pom.xml Maven Configuration Problem: Unknown)
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.5.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.abc</groupId>
<artifactId>spring-data-jpa-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-data-jpa-demo</name>
<description>Spring Boot With Spring Data JPA</description>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version><!-- 加上這個 -->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</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>
因為要連接MySQL資料庫,所以要在<dependencies>
中加入MySQL JDBC connector J的依賴。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
接著開啟Spring Boot預設放在src/main/resources
下的application.properties
設定檔,加入MySQL的datasource連線及JPA等設定如下。
以下我改用application.yml
來設定。
application.yml
# DataSource配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: matt
password: 12345
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: update
相當於
application.properties
# DataSource配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=matt
spring.datasource.password=12345
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# hibernate 5.3.1後新增了MYSQL8Dialect
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
接著建立以下幾個類別及介面。
com.abc.app.entity.Customer
com.abc.app.model.CustomerBo
com.abc.app.dao.CustomerDao
com.abc.app.service.CustomerService
Customer
類別為ORM的實體(Entity)類,所以類別名稱上要掛@Entity
,因此會與mydb.customer
資料表互相映射。主鍵為掛上@Id
的id
屬性。
Customer
package com.abc.app.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Customer {
@Id
private Long id;
private String name;
private String address;
@Override
public String toString() {
return String.format("Customer[id=%d, name='%s', address='%s']", id,
name, address);
}
// getters and setters...
}
CustomerBo
為從資料庫取回Customer
實體後,負責裝載Service層處理商業邏輯時的Model類別。
CustomerBo
package com.abc.app.model;
public class CustomerBo {
private Long id;
private String name;
private String address;
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("id:" + id + ",");
sb.append("name:" + name + ",");
sb.append("address:" + address);
return sb.toString();
}
// getters and setters...
}
CustomerDao
為掛有@Repository
的資料存取層,負責對資料庫進行存取,這邊繼承了Spring Data的CrudRepository
,所以預設會有基本的CRUD方法可以呼叫。
CustomerDao
package com.abc.app.dao;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.abc.app.entity.Customer;
@Repository
public interface CustomerDao extends CrudRepository<Customer, Long>{
}
CustomerService
為Service層,做為一般Web應用程式Controller與Dao (Repository)的中間層,本範例沒有寫Controller,而是直接在Spring Boot啟動時從SpringBootApplication類,也就是SpringDataJpaDemoApplication
直接呼叫來進行測試。
CustomerService
package com.abc.app.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.abc.app.dao.CustomerDao;
import com.abc.app.entity.Customer;
import com.abc.app.model.CustomerBo;
@Service
public class CustomerService {
@Autowired
private CustomerDao customerDao;
public void add(CustomerBo bo) {
Customer entity = new Customer();
entity.setId(bo.getId());
entity.setName(bo.getName());
entity.setAddress(bo.getAddress());
customerDao.save(entity);
}
public CustomerBo get(long id) {
Customer entity = customerDao.findById(id).orElse(new Customer());
CustomerBo bo = new CustomerBo();
bo.setId(entity.getId());
bo.setName(entity.getName());
bo.setAddress(entity.getAddress());
return bo;
}
}
本範例直接在SpringDataJpaDemoApplication
呼叫CustomerService
來測試。在Spring Boot的進入點SpringDataJpaDemoApplication.main()
方法中將內容修改如下。
SpringDataJpaDemoApplication
package com.abc.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.abc.app.model.CustomerBo;
import com.abc.app.service.CustomerService;
@SpringBootApplication
public class SpringDataJpaDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
SpringApplication.run(SpringDataJpaDemoApplication.class, args); // 取得Spring Context
CustomerService customerService = context.getBean(CustomerService.class); // 取得CustomerService的bean
CustomerBo bo1 = new CustomerBo();
bo1.setId(10001L);
bo1.setName("John");
bo1.setAddress("No. 7, Yixin St., Hualien City, Hualien County 970, Taiwan (R.O.C.)");
customerService.add(bo1); // 新增
CustomerBo bo2 = customerService.get(10001L); // 查詢
System.out.println(bo2);
}
}
接著啟動Spring Boot應用程式,Spring Data JPA便會依照實體類,也就是Customer
的設定幫我們在mydb
資料庫建立好對映的customer
資料表,並新增一筆資料,然後再查詢出來。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.4.RELEASE)
2019-05-19 15:30:25.247 INFO 13420 --- [ main] c.abc.app.SpringDataJpaDemoApplication : Starting SpringDataJpaDemoApplication on matt-PC with PID 13420 (D:\MyProject\spring-boot\workspace\spring-data-jpa-demo\target\classes started by matt in D:\MyProject\spring-boot\workspace\spring-data-jpa-demo)
2019-05-19 15:30:25.250 INFO 13420 --- [ main] c.abc.app.SpringDataJpaDemoApplication : No active profile set, falling back to default profiles: default
2019-05-19 15:30:25.776 INFO 13420 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2019-05-19 15:30:25.833 INFO 13420 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 50ms. Found 1 repository interfaces.
2019-05-19 15:30:26.245 INFO 13420 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-05-19 15:30:26.902 INFO 13420 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-05-19 15:30:26.950 INFO 13420 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2019-05-19 15:30:27.008 INFO 13420 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.3.9.Final}
2019-05-19 15:30:27.011 INFO 13420 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2019-05-19 15:30:27.168 INFO 13420 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
2019-05-19 15:30:27.344 INFO 13420 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2019-05-19 15:30:28.448 INFO 13420 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2019-05-19 15:30:28.779 INFO 13420 --- [ main] c.abc.app.SpringDataJpaDemoApplication : Started SpringDataJpaDemoApplication in 3.861 seconds (JVM running for 4.702)
id:10001,name:John,address:No. 7, Yixin St., Hualien City, Hualien County 970, Taiwan (R.O.C.)
2019-05-19 15:30:29.010 INFO 13420 --- [ Thread-3] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2019-05-19 15:30:29.019 INFO 13420 --- [ Thread-3] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2019-05-19 15:30:29.027 INFO 13420 --- [ Thread-3] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
在MySQL Workbench檢查mydb.customer
確實有一筆剛剛新增的資料。
完成後的專案目錄結構。
若文章對您有幫助還幫忙點個廣告鼓勵,謝謝您的支持。
5 則留言:
想問一下若是直接對entity存取會有什麼樣的問題嗎@@?
不會有什麼問題,只是習慣上Service層和Dao層會切開
請問在services中
entity.setId(bo.getId());
entity.setName(bo.getName());
entity.setAddress(bo.getAddress());
IED一直跑出cannot resolve method setId in 'Customer'
setName setAddress這些方法也是
這些物件方法都無法被解析
@ronidog Customer, CustomerBo中的 // getters and setters... 代表省略的意思,你需要在你的程式中補上,我這邊沒有寫出來。
感謝大大回達這麼迅速 我太菜了@@
張貼留言