架構小白到磚家-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,事物