1. 程式人生 > >架構小白到磚家-07-儲存層JPA初體驗-不寫SQL操作資料庫

架構小白到磚家-07-儲存層JPA初體驗-不寫SQL操作資料庫

終於把使用者請求問題處理完畢了,接下來可以解決web應用第二個問題,資料儲存問題。咱們在應用框架發展歷史中已經知道了,資料儲存框架經過了純JDBC,到EJB重量級框架,在到springAOP切面程式設計+spring的輕量級容器,然後到ORM框架hibernate,最後到JPA統一ORM標準。那麼springJPA到底是怎麼使用呢?
在這裡插入圖片描述
根據面向物件程式設計思想,java操作資料庫,應該使用物件操作的方式,而不是直接使用sql的方式。那麼就需要解決如何將資料庫的錶轉化成java物件的問題?目前spring的用法就是註解,那麼JPA肯定也是用註解來關聯java物件和表的對映關係。
首先我們還是先把JPA整合到springboot中,老規矩第一步告訴maven引入jpa的jar;第二步告訴springboot關於資料庫的資訊,在application.properties中配置jpa和datasource的資訊;第三步建立javabean和資料庫表對映關係。在ORM技術中,javabean不光能對映表關係,還能通過javabean建立和修改資料庫表結構。

pom.xml檔案中加入

		<!-- spring boot JPA -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
			<version>${spring.boot.version}</version>
		</dependency>

		<!-- Druid -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.20</version>
		</dependency>
		<!-- MYSQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.13</version>
		</dependency>

application.properties檔案中加入

#資料庫相關配置
spring.jpa.show-sql=false
#spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.hibernate.ddl-auto=create

# 資料庫訪問配置
# 主資料來源,預設的
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=${app.datasource.url}
spring.datasource.username=${app.datasource.username}
spring.datasource.password=${app.datasource.password}

# 下面為連線池的補充設定,應用到上面所有資料來源中
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=60
# 配置獲取連線等待超時的時間
spring.datasource.maxWait=60000
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一個連線在池中最小生存的時間,單位是毫秒 
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 開啟PSCache,並且指定每個連線上PSCache的大小 
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=40
# 配置監控統計攔截的filters,去掉後監控介面sql無法統計,'wall'用於防火牆 
spring.datasource.filters=stat,wall,log4j
# 通過connectProperties屬性來開啟mergeSql功能;慢SQL記錄
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合併多個DruidDataSource的監控資料
spring.datasource.useGlobalDataSourceStat=true

建立一個User.java

@Entity()
@Table(name="P_USER")
public class User {
	@TableGenerator(
			name="ID_GENERATOR",//該主鍵生成策略的名稱,與 @GeneratedValue 的 generator 屬性值對應
			table="jpa_id_generators",// 指明根據哪個表生成主鍵
			pkColumnName="PK_NAME",// 使用 pkColumnName pkColumnValue valueColumnName 三個屬性唯一的定位一個點
			pkColumnValue="p_user_id",//實體的主鍵名稱
			valueColumnName="PK_VALUE",//實體的主鍵值
			allocationSize=1,//指定每次增加的數量
			initialValue=1)//初始化主鍵值
	@GeneratedValue(strategy=GenerationType.TABLE, generator="ID_GENERATOR")
	@Id
	private long id;
	//賬號
	private String username;
	//密碼
	private String password;
	//電子郵件 
	private String email;
	//可用性
	private boolean available = true;
	//真實姓名
	private String realName;
	//電話
	private String phone;
	//新增時間
	private Date createTime; 	
	//更新時間
	private Date updateTime; 

啟動應用後,我們檢視資料庫,就會生成對應的P_USER這張表。
在這裡插入圖片描述

相關的配置檔案資訊大家看看註釋,我們還是主要關注spring-jpa的註解,首先需要告訴spring我們的User.java是一個數據庫表的實體@Entity();然後告訴jpa我們的User是對應資料庫中的那張表@Table(name=“P_USER”);最後得給表設定一個唯一主鍵約束,我們採用了可以跨資料庫的方案@TableGenerator和@GeneratedValue(),使用建立一張主鍵表來讓JPA管理每張表的主鍵自增邏輯。詳細配置大家也自己看看註釋。

OK,咱們已經邁出了第一步,搞定了資料庫和java物件的關聯問題,那麼下面我們就來儲存資料吧。JPA的基本想法很厲害,就是讓開發人員忘記資料庫的存在。怎麼實現這個想法呢?首先JPA提供了常用的操作資料庫工具,叫做Repository,直接繼承這個介面工具,無需實現介面,就能操作資料庫了。聽上去很神奇,只建立介面,不做實現,怎麼可能?其實jpa還是有實現的,只是不需要大家自己去實現了,這裡我截取了jpa的繼承關係。
在這裡插入圖片描述
Repository預設是沒有功能的,通過面向物件思想的繼承特性,擴展出了資料庫表的基本增刪改查操作的CrudRepository,又繼續擴充套件了分頁和排序能力PagingAndSortingRepository,最後統一成了JpaRepository工具。預設jpa提供了SimpleJpaRepository實現類。

那麼我們就建立一個自己的UserRepository介面,來進行資料庫操作吧。

public interface UserRepository extends JpaRepository<User, Long> 

為了驗證方便,咱們就採用單元測試的方式來操作資料庫。
在這裡插入圖片描述
在這裡插入圖片描述

我們可以看到沒有寫任何實現和一句SQL,咱們就可以通過操作物件的方式,往資料庫裡面插入了這麼多資料。其他的修改和刪除,這裡就寫下案例,就不執行結果了。jpa真的實現了讓我們忘記資料庫的存在,完全是操作java物件的方式在處理資料儲存。
在這裡插入圖片描述

但是這些簡單的單表操作,怎麼解決帶查詢條件的SQL查詢呢?還能不寫sql可以做到嗎?JPA還真提供了一種方法,那就是通過在介面宣告查詢方法,方法的名稱按特定的格式,就可以讓jpa自動生成查詢sql。讓我們來看看這種方法吧。

UserRepository檔案中加入
在這裡插入圖片描述
單元測試中新增
在這裡插入圖片描述
在這裡插入圖片描述

厲害了,真的能查詢出來,它是怎麼做到的?底層原因我們就不深度探究了,來看看我們宣告的方法,到底寫了什麼?

	User findByRealName(String realName);
	User findByUsernameOrEmail(String username,String email);

findByRealName,我們就寫了一句英語,大概意思就是告訴jpa用realName這個條件,給我們找出一個User來。沒錯,就是用英文的大白話,讓jpa查詢資料。那還有哪些查詢條件用法呢?我去spring官網獲取了一張說明。
在這裡插入圖片描述

好吧,我佩服。難道jpa真的就能無敵到能解決所有sql查詢的情況嗎?這個問題,咱們下一篇在探討吧。

總結回顧,資料儲存通過jpa框架來實現,它是面向物件的思想來操作資料庫,想讓開發人員忘記資料庫的存在,並且還想讓開發人員不寫程式碼實現,就宣告資料操作介面方法,用最簡單的英文大白話告訴jpa去查詢資料。總結下springjpa的常用註解。

@Table,對映表
@Entity,對映實體
@Id,主鍵
@GeneratedValue,主鍵生成策略
@Column,欄位對映
@Transient,忽略對映
@Cacheable,是否使用二級快取
@NamedQuery,提前準備JPQL
@Query,Repository方法指定查詢JPQL
@Modifying,配合 @Query 可以完成 UPDATE 和 DELETE 操作
@Transactional,事物