一文搞懂 Spring JPA

2021-01-08 CSDN

作者 | 阿文

責編 | 屠敏

什麼是 JPA

大家好,今天我和大家聊一下關於Spring JPA 的相關知識,我們先來了解下什麼是 JPA ?

JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化規範。它為 Java 開發人員提供了一種對象/關聯映射工具來管理 Java 應用中的關係數據。他的出現主要是為了簡化現有的持久化開發工作和整合 ORM 技術,結束現在 Hibernate,TopLink,JDO 等 ORM 框架各自為營的凌亂局面。JPA 在充分吸收了現有 Hibernate,TopLink,JDO 等ORM框架的基礎上發展而來的,具有易於使用,伸縮性強等優點。從上面的解釋中我們可以了解到JPA 是一套規範,而類似 Hibernate,TopLink,JDO 這些產品是實現了 JPA 規範。

了解了什麼是 JPA,我們來看看本文的主角——spring data jpa。

spring data jpa

Spring Data JPA 是 Spring 基於 ORM 框架、JPA 規範的基礎上封裝的一套 JPA 應用框架,底層使用了 Hibernate 的 JPA 技術實現,可使開發者用極簡的代碼即可實現對數據的訪問和操作。它提供了包括增刪改查等在內的常用功能,且易於擴展!學習並使用 Spring Data JPA 可以極大提高開發效率。

什麼意思呢?如果用過Hibernate或者MyBatis的話,就會知道對象關係映射(ORM)框架有多麼方便。但是Spring Data JPA框架功能更進一步,為我們做了 一個數據持久層框架幾乎能做的任何事情。以Springboot整合MyBatis為例,比如我們要向資料庫中插入一些用戶的數據,那麼我們需要先定義用戶的實體類,然後我們要定義一個UserDao:

@RepositorypublicclassUserDao{@Autowired JdbcTemplate jdbcTemplate;publicintaddUser(User user){return jdbcTemplate.update("INSERT INTO t_user(username,jobs,phone) VALUE (?,?,?)", user.getName(),user.getJobs(),user.getPhone()); }publicintupdateUser(User user){return jdbcTemplate.update("UPDATE t_user SET username=?,jobs=?,phone=? WHERE id=?", user.getName(),user.getJobs(),user.getPhone(),user.getId()); }publicintdeleteUser(Integer id){return jdbcTemplate.update("DELETE FROM t_user WHERE id=?",id); }public User getUserById(Integer id){return jdbcTemplate.queryForObject("SELECT * FROM t_user WHERE id =?",new BeanPropertyRowMapper<>(User.class),id); }public List<User> getAllUser(){return jdbcTemplate.query("SELECT * FROM t_user",new BeanPropertyRowMapper<>(User.class)); }}

以及UserService

@ServicepublicclassUserService{@Autowired UserDao userDao;publicintaddUser(User user){return userDao.addUser(user); }publicintupdateUser(User user){return userDao.updateUser(user); }publicintdeleteUser(Integer id){return userDao.deleteUser(id); }public User getUserById(Integer id){return userDao.getUserById(id); }public List<User> getAllUser(){return userDao.getAllUser(); }}

最後,我們在去調用對應的service 中的方法。這是傳統的方式,如果使用mapper,會稍微簡單一些,比如我們要添加mapper

@MapperpublicinterfaceUserMapper{intaddUser(User user);intdeleteUser(int id);intupdateUser(User user);User getUserById(Integer id);List<User> getAllUsers();}

然後定義一個UserMapper.xml ,添加對應的CURD SQL語句,做好映射,然後改造service,例如

@ServicepublicclassUserService{@Autowired UserMapper userMapper;publicintaddUser(User user){return userMapper.addUser(user); }publicintupdateUser(User user){return userMapper.updateUser(user); }publicintdeleteUser(Integer id){return userMapper.deleteUser(id); }public User getUserById(Integer id){return userMapper.getUserById(id); }public List<User> getAllUser(){return userMapper.getAllUsers(); }}

發現什麼問題了嗎?如果我們要去實現多個表的操作,我們需要定義不同的實體類,然後實現對應的mapper,然後寫同樣的增刪改查方法,最後調用。這也太麻煩了些,而Spring data jpa 則可以輕鬆的幫我們實現這些繁瑣重複且沒有技術含量的操作。我們一起看下吧!

案例演示

1.首先,我們需要配置pom.xml

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

2.然後是application.properties 的配置

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=truespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.jpa.properties.hibernate.hbm2ddl.auto=createspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialectspring.jpa.show-sql=true

這裡重點簡單介紹下spring.jpa.properties.hibernate.hbm2ddl.auto有幾種配置:

create:表示每次加載Hibernate時都會刪除上一次生成的表(包括數據),然後重新生成新表,即使兩次沒有任何修改也會這樣執行。適用於每次執行單測前清空資料庫的場景。create-drop:表示每次加載Hibernate時都會生成表,但當SessionFactory關閉時,所生成的表將自動刪除。update:最常用的屬性值,第一次加載Hibernate時創建數據表(前提是需要先有資料庫),以後加載Hibernate時不會刪除上一次生成的表,會根據實體更新,只新增欄位,不會刪除欄位(即使實體中已經刪除)。validate:每次加載Hibernate時都會驗證數據表結構,只會和已經存在的數據表進行比較,根據model修改表結構,但不會創建新表。不配置此項,表示禁用自動建表功能spring.jpa.show-sql=true 該配置當在執行資料庫操作的時候會在控制臺列印 sql 語句,方便我們檢查排錯等。

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect 這是資料庫的方言配置。

3.接下來我們建立用戶實體類

@EntitypublicclassUser{@Id@GeneratedValueprivatelong id;@Column(nullable = false, unique = true)private String userName;@Column(nullable = false)private String password;@Column(nullable = false)privateint age;}

這裡的一些註解解釋如下:

@Entity 是一個類註解,用來註解該類是一個實體類用來進行和資料庫中的表建立關聯關係,首次啟動項目的時候,默認會在數據中生成一個同實體類相同名字的表(table),也可以通過註解中的 name 屬性來修改表(table)名稱, 如@Entity(name=「user」) , 這樣資料庫中表的名稱則是 user 。該註解十分重要,如果沒有該註解首次啟動項目的時候你會發現資料庫沒有生成對應的表。@Table 註解也是一個類註解,該註解可以用來修改表的名字,該註解完全可以忽略掉不用,@Entity 註解已具備該註解的功能。@Id 類的屬性註解,該註解表明該屬性欄位是一個主鍵,該屬性必須具備,不可缺少。@GeneratedValue 該註解通常和 @Id 主鍵註解一起使用,用來定義主鍵的呈現形式,該註解通常有多種使用策略,先總結如下:@GeneratedValue(strategy= GenerationType.IDENTITY) 該註解由資料庫自動生成,主鍵自增型,在 mysql 資料庫中使用最頻繁,oracle 不支持。@GeneratedValue(strategy= GenerationType.AUTO) 主鍵由程序控制,默認的主鍵生成策略,oracle 默認是序列化的方式,mysql 默認是主鍵自增的方式。@GeneratedValue(strategy= GenerationType.SEQUENCE) 根據底層資料庫的序列來生成主鍵,條件是資料庫支持序列,Oracle支持,Mysql不支持。@GeneratedValue(strategy= GenerationType.TABLE) 使用一個特定的資料庫表格來保存主鍵,較少使用。上面這些主鍵生成策略中,以 mysql 為例, IDENTITY 和 AUTO 用的較多,二者當中 IDENTITY 用的多些,以下文章當中演示的 demo 主鍵均使用 @GeneratedValue(strategy= GenerationType.IDENTITY) 的生成策略。

@Column 是一個類的屬性註解,該註解可以定義一個欄位映射到資料庫屬性的具體特徵,比如欄位長度,映射到資料庫時屬性的具體名字等。

@Transient 是一個屬性註解,該註解標註的欄位不會被映射到資料庫當中。

4. 聲明 `UserRepository`接口,繼承`JpaRepository`,如下所示

publicinterfaceUserRepositoryextendsJpaRepository<User, Long> {}

這裡的 JpaRepository繼承了接口PagingAndSortingRepository和QueryByExampleExecutor。而,PagingAndSortingRepository又繼承CrudRepository。

因此,JpaRepository接口同時擁有了基本CRUD功能以及分頁功能。因此,這裡我們可以繼承JpaRepository,從而獲得Spring為我們預先定義的多種基本數據操作方法。

5.然後我們定義一個測試類, 這裡我們演示下添加操作, @Transactional 表示開啟事務防止出現髒數據。

……@Autowiredprivate UserRepository userRepository;@Test@TransactionalpublicvoiduserAddTest(){ User user = new User(); user.setUserName("吳彥祖"); user.setAge(30); user.setPassword("123456"); userRepository.save(user); User item = userRepository.findByUserName("wyk"); log.info(JsonUtils.toJson(item)); }

6.接下來我們說下查詢,查詢可以分為基本查詢和自定義查詢,一種是 spring data 默認已經實現,只需要要繼承`JpaRepository`,一種是根據查詢的方法來自動解析成 SQL。

@TestpublicvoidtestQuery()throws Exception { User user=new User(); userRepository.findAll(); userRepository.findOne(1l); userRepository.save(user); userRepository.delete(user); userRepository.count(); userRepository.exists(1l); ……}

7.自定義的簡單查詢就是根據方法名來自動生成SQL,主要的語法是`findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy`後面跟屬性名稱,舉幾個例子:

User findByUserName(String userName);User findByUserNameOrEmail(String username, String email);Long deleteById(Long id);Long countByUserName(String userName);List<User> findByEmailLike(String email);User findByUserNameIgnoreCase(String userName);List<User> findByUserNameOrderByEmailDesc(String email);

8.接下來,我們說下複雜的查詢,在實際的開發中我們需要用到分頁、刪選、連表等查詢的時候就需要特殊的方法或者自定義 SQL,以分頁查詢為例,分頁查詢在實際使用中非常普遍了,spring data jpa已經幫我們實現了分頁的功能,在查詢的方法中,需要傳入參數Pageable,當查詢中有多個參數的時候Pageable建議做為最後一個參數傳入。Pageable是 spring 封裝的分頁實現類,使用的時候需要傳入頁數、每頁條數和排序規則

Page<User> findALL(Pageable pageable);Page<User> findByUserName(String userName,Pageable pageable);

9.我們看下下面的測試用例

@TestpublicvoidtestPageQuery()throws Exception {int page=1,size=5; Sort sort = new Sort(Direction.DESC, "id"); Pageable pageable = new PageRequest(page, size, sort); userRepository.findALL(pageable); userRepository.findByUserName("testName", pageable);}

10. Spring data 大部分的 SQL 都可以根據方法名定義的方式來實現,但是由於某些原因我們想使用自定義的 SQL 來查詢,spring data 也是完美支持的,如下所示:

@Modifying@Query("update User u set u.userName = ?1 where c.id = ?2")int modifyByIdAndUserId(String userName, Long id);@Transactional@Modifying@Query("delete from User where id = ?1")void deleteByUserId(Long id);@Transactional(timeout = 10)@Query("select u from User u where u.emailAddress = ?1")User findByEmailAddress(String emailAddress);

好啦,以上就是關於spring data jpa 的介紹。

相關焦點

  • 一文搞懂如何在Spring Boot 正確中使用JPA
    一 JPA 基礎:常見操作1.相關依賴我們需要下面這些依賴支持我們完成這部分內容的學習: <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <
  • 詳述 Spring Data JPA 的那些事兒
    jpa 的全稱是 Java Persistence API  , 中文的字面意思就是 java 的持久層 API , jpa 就是定義了一系列標準,讓實體類和資料庫中的表建立一個對應的關係,當我們在使用 java 操作實體類的時候能達到操作資料庫中表的效果(不用寫sql ,就可以達到效果),jpa 的實現思想即是 ORM (Object Relation Mapping),對象關係映射,用於在關係型資料庫和業務實體對象之間作一個映射
  • SpringBoot(五) :spring data jpa 的使用
    的使用.html如有好文章投稿,請點擊 → 這裡了解詳情在上篇文章《 springboot(二):web綜合開發 》中簡單介紹了一下spring data jpa的基礎性使用,這篇文章將更加全面的介紹spring data jpa 常見用法以及注意事項。
  • springboot(五):spring data jpa的使用
    在上篇文章springboot(二):web綜合開發中簡單介紹了一下spring data jpa的基礎性使用,這篇文章將更加全面的介紹spring
  • Spring Boot的JPA / Hibernate複合主鍵示例
    該屬性spring.jpa.hibernate.ddl-auto = update使應用程式中的實體類型和映射的資料庫表保持同步。每當更新域實體時,下次重新啟動應用程式時,資料庫中相應的映射表也將更新。這非常適合開發,因為您不需要手動創建或更新表。它們將根據應用程式中的Entity類自動創建/更新。
  • MyBatis JPA Extra,MyBatis JPA 擴展 v2.2 發布
    MyBatis JPA ExtraMyBatis JPA Extra對MyBatis進行了JPA擴展,旨在基於JPA 2.1的注釋簡化對單表CUID操作,根據JPA注釋動態生成SQL語句;使用Interceptor實現資料庫SELECT分頁查詢,適配多種資料庫;另外提供mybatis-jpa-extra-spring-boot-starter
  • springboot+jpa+thymeleaf實現信息增刪改查功能
    前端:thymeleaf後端:springboot+jpa資料庫:mysql5.6jdk:1.8及以上</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId>        </dependency> <dependency> <groupId>mysql</groupId>
  • SpringBoot從入門到放棄之配置Spring-Data-JPA自動建表
    pom文件配置引入依賴配置文件進行jpa配置這裡有兩個配置需要說明一下;show_sql: true 在控制臺顯示jpa生成的s
  • SpringData JPA就是這麼簡單
    一、SpringData入門在上次學SpringBoot的時候,那時候的教程就已經涉及到了一點SpringData JPA的知識了。當時還是第一次見,覺得也沒什麼大不了,就是封裝了Hibernate的API而已。然後在慕課網上又看到了SpringData的教程了。於是就進去學習了一番。
  • 五分鐘學Java:一篇文章搞懂spring和springMVC
    相信很多人和我一樣,第一次了解spring都不是做項目的時候用到,而是在網上看到或者是聽到過一個叫做spring的框架,這個框架號稱完爆之前的structs和structs2,吸引了不少人的注意。那麼,spring到底有沒有神奇呢,據記載,spring框架出現的時間是在2002年,當時的人們對於繁瑣笨重的EJB框架詬病不已,而且對於structs這類框架也沒有什麼好感,這個時候spring從天而,救一大批Java開發者於水火之中。
  • Spring JPA中文教程之 JPA 介紹
    前面的配置類使用的EmbeddedDatabaseBuilderAPI 建立了嵌入式HSQL資料庫spring-jdbc。然後,Spring Data會設置一個,EntityManagerFactory並使用Hibernate作為示例持久性提供程序。在此聲明的最後一個基礎結構組件是JpaTransactionManager。
  • Spring Boot 實現RESTful webservice服務端示例
    createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true username: root password: 123456 jpa: hibernate: ddl-auto
  • Spring Cloud Connectors 1.2.0 發布
    ConfigurationThere was an issue with nested @Configuration classes that extend AbstractCloudConfig triggering ClassNotFound exceptions when spring-data-jpa
  • Spring事務管理
    一、Spring事務管理的特點Spring框架為事務管理提供一套統一的抽象,帶來的好處有:1.
  • Spring Boot 和 Spring 到底有啥區別?
    ;org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.0.RELEASE</version></dependency><dependency> <groupId
  • 學習學習SpringSecurity
    ;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
  • Spring 和 Spring Boot 之間到底有啥區別?
    3、提供的 starters 簡化構建配置4、儘可能自動配置 spring應用。>spring-web</artifactId><version>5.1.0.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><
  • 為啥國人喜歡Mybatis,而老外偏愛 Hibernate/JPA 呢?
    昨天又跟群裡的小夥伴進行了一番討論,感觸還是有一些,於是就有了今天這篇文。聲明:本文不會下關於 Mybatis 和 JPA 兩個持久層框架哪個更好這樣的結論。只是擺事實,講道理,所以,請各位看官勿噴。一、事件起因關於 Mybatis 和 JPA 孰優孰劣的問題,爭論已經很多年了。
  • mongoHelper 0.3.9 發布,spring-data-mongodb 增強工具包
    mongoHelper 是基於 spring-data-mongodb 的增強工具包,簡化 CRUD 操作,提供類 jpa 的資料庫操作。
  • 一文搞懂代數幾何發展史(一)
    本文作者陳躍,原文題目《什麼是代數幾何》,因文章長度限制將文章分成兩部分:第1部分《一文搞懂代數幾何發展史(一)》為20世紀早期及以前的很長一段時間內數學家們對代數簇的深入研究;第2部分《一文搞懂代數幾何發展史(二)》講述從將抽象代數方法引入代數幾何到概形理論的創立這一時期的發現情況。歡迎品鑑,一文搞懂代數幾何發展史。