Spring Boot中使用Spring-data-jpa實現(xiàn)數(shù)據(jù)庫增刪查改
在實際開發(fā)過程中,對數(shù)據(jù)庫的操作無非就“增刪改查”。就最為普遍的單表操作而言,除了表和字段不同外,語句都是類似的,開發(fā)人員需要寫大量類似而枯燥的語句來完成業(yè)務邏輯。
為了解決這些大量枯燥的數(shù)據(jù)操作語句,我們第一個想到的是使用ORM框架,比如:Hibernate。通過整合Hibernate之后,我們以操作Java實體的方式最終將數(shù)據(jù)改變映射到數(shù)據(jù)庫表中。
為了解決抽象各個Java實體基本的“增刪改查”操作,我們通常會以泛型的方式封裝一個模板Dao來進行抽象簡化,但是這樣依然不是很方便,我們需要針對每個實體編寫一個繼承自泛型模板Dao的接口,再編寫該接口的實現(xiàn)。雖然一些基礎(chǔ)的數(shù)據(jù)訪問已經(jīng)可以得到很好的復用,但是在代碼結(jié)構(gòu)上針對每個實體都會有一堆Dao的接口和實現(xiàn)。
由于模板Dao的實現(xiàn),使得這些具體實體的Dao層已經(jīng)變的非?!氨 ?,有一些具體實體的Dao實現(xiàn)可能完全就是對模板Dao的簡單代理,并且往往這樣的實現(xiàn)類可能會出現(xiàn)在很多實體上。Spring-data-jpa的出現(xiàn)正可以讓這樣一個已經(jīng)很“薄”的數(shù)據(jù)訪問層變成只是一層接口的編寫方式。比如,下面的例子:
public interface UserRepository extends JpaRepository<User, Long> { User findByName(String name); @Query("from User u where u.name=:name") User findUser(@Param("name") String name); }
我們只需要通過編寫一個繼承自JpaRepository的接口就能完成數(shù)據(jù)訪問,下面以一個具體實例來體驗Spring-data-jpa給我們帶來的強大功能。
使用示例
由于Spring-data-jpa依賴于Hibernate。如果您對Hibernate有一定了解,下面內(nèi)容可以毫不費力的看懂并上手使用Spring-data-jpa。如果您還是Hibernate新手,您可以先按如下方式入門,再建議回頭學習一下Hibernate以幫助這部分的理解和進一步使用。
工程配置
在pom.xml中添加相關(guān)依賴,加入以下內(nèi)容:
<dependency <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
在application.xml中配置:數(shù)據(jù)庫連接信息(如使用嵌入式數(shù)據(jù)庫則不需要)、自動創(chuàng)建表結(jié)構(gòu)的設(shè)置,例如使用mysql的情況如下:
spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop
spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置屬性,其主要作用是:自動創(chuàng)建、更新、驗證數(shù)據(jù)庫表結(jié)構(gòu)。該參數(shù)的幾種配置如下:
create:每次加載hibernate時都會刪除上一次的生成的表,然后根據(jù)你的model類再重新來生成新表,哪怕兩次沒有任何改變也要這樣執(zhí)行,這就是導致數(shù)據(jù)庫表數(shù)據(jù)丟失的一個重要原因。
create-drop:每次加載hibernate時根據(jù)model類生成表,但是sessionFactory一關(guān)閉,表就自動刪除。
update:最常用的屬性,第一次加載hibernate時根據(jù)model類會自動建立起表的結(jié)構(gòu)(前提是先建立好數(shù)據(jù)庫),以后加載
hibernate時根據(jù)model類自動更新表結(jié)構(gòu),即使表結(jié)構(gòu)改變了但表中的行仍然存在不會刪除以前的行。要注意的是當部署到服務器后,表結(jié)構(gòu)是不會被馬上建立起來的,是要等應用第一次運行起來后才會。
validate:每次加載hibernate時,驗證創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu),只會和數(shù)據(jù)庫中的表進行比較,不會創(chuàng)建新表,但是會插入新值。
至此已經(jīng)完成基礎(chǔ)配置,如果您有在Spring下整合使用過它的話,相信你已經(jīng)感受到Spring Boot的便利之處:JPA的傳統(tǒng)配置在persistence.xml文件中,但是這里我們不需要。當然,最好在構(gòu)建項目時候按照之前提過的最佳實踐的工程結(jié)構(gòu)來組織,這樣以確保各種配置都能被框架掃描到。
創(chuàng)建實體
創(chuàng)建一個User實體,包含id(主鍵)、name(姓名)、age(年齡)屬性,通過ORM框架其會被映射到數(shù)據(jù)庫表中,由于配置了hibernate.hbm2ddl.auto,在應用啟動的時候框架會自動去數(shù)據(jù)庫中創(chuàng)建對應的表。
@Entity public class User { @Id @GeneratedValue private Long id; @Column(nullable = false) private String name; @Column(nullable = false) private Integer age; // 省略構(gòu)造函數(shù) // 省略getter和setter }
創(chuàng)建數(shù)據(jù)訪問接口
下面針對User實體創(chuàng)建對應的Repository接口實現(xiàn)對該實體的數(shù)據(jù)訪問,如下代碼:
public interface UserRepository extends JpaRepository<User, Long> { User findByName(String name); User findByNameAndAge(String name, Integer age); @Query("from User u where u.name=:name") User findUser(@Param("name") String name); }
在Spring-data-jpa中,只需要編寫類似上面這樣的接口就可實現(xiàn)數(shù)據(jù)訪問。不再像我們以往編寫了接口時候還需要自己編寫接口實現(xiàn)類,直接減少了我們的文件清單。
下面對上面的UserRepository做一些解釋,該接口繼承自JpaRepository,通過查看JpaRepository接口的API文檔,可以看到該接口本身已經(jīng)實現(xiàn)了創(chuàng)建(save)、更新(save)、刪除(delete)、查詢(findAll、findOne)等基本操作的函數(shù),因此對于這些基礎(chǔ)操作的數(shù)據(jù)訪問就不需要開發(fā)者再自己定義。
在我們實際開發(fā)中,JpaRepository接口定義的接口往往還不夠或者性能不夠優(yōu)化,我們需要進一步實現(xiàn)更復雜一些的查詢或操作。由于本文重點在spring boot中整合spring-data-jpa,在這里先拋磚引玉簡單介紹一下spring-data-jpa中讓我們興奮的功能,后續(xù)再單獨開篇講一下spring-data-jpa中的常見使用。
在上例中,我們可以看到下面兩個函數(shù):
User findByName(String name) User findByNameAndAge(String name, Integer age)
它們分別實現(xiàn)了按name查詢User實體和按name和age查詢User實體,可以看到我們這里沒有任何類SQL語句就完成了兩個條件查詢方法。這就是Spring-data-jpa的一大特性:通過解析方法名創(chuàng)建查詢。
除了通過解析方法名來創(chuàng)建查詢外,它也提供通過使用@Query 注解來創(chuàng)建查詢,您只需要編寫JPQL語句,并通過類似“:name”來映射@Param指定的參數(shù),就像例子中的第三個findUser函數(shù)一樣。
Spring-data-jpa的能力遠不止本文提到的這些,由于本文主要以整合介紹為主,對于Spring-data-jpa的使用只是介紹了常見的使用方式。諸如@Modifying操作、分頁排序、原生SQL支持以及與Spring MVC的結(jié)合使用等等內(nèi)容就不在本文中詳細展開,這里先挖個坑,后續(xù)再補文章填坑,如您對這些感興趣可以關(guān)注我博客或簡書,同樣歡迎大家留言交流想法。
單元測試
在完成了上面的數(shù)據(jù)訪問接口之后,按照慣例就是編寫對應的單元測試來驗證編寫的內(nèi)容是否正確。這里就不多做介紹,主要通過數(shù)據(jù)操作和查詢來反復驗證操作的正確性。
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(Application.class) public class ApplicationTests { @Autowired private UserRepository userRepository; @Test public void test() throws Exception { // 創(chuàng)建10條記錄 userRepository.save(new User("AAA", 10)); userRepository.save(new User("BBB", 20)); userRepository.save(new User("CCC", 30)); userRepository.save(new User("DDD", 40)); userRepository.save(new User("EEE", 50)); userRepository.save(new User("FFF", 60)); userRepository.save(new User("GGG", 70)); userRepository.save(new User("HHH", 80)); userRepository.save(new User("III", 90)); userRepository.save(new User("JJJ", 100)); // 測試findAll, 查詢所有記錄 Assert.assertEquals(10, userRepository.findAll().size()); // 測試findByName, 查詢姓名為FFF的User Assert.assertEquals(60, userRepository.findByName("FFF").getAge().longValue()); // 測試findUser, 查詢姓名為FFF的User Assert.assertEquals(60, userRepository.findUser("FFF").getAge().longValue()); // 測試findByNameAndAge, 查詢姓名為FFF并且年齡為60的User Assert.assertEquals("FFF", userRepository.findByNameAndAge("FFF", 60).getName()); // 測試刪除姓名為AAA的User userRepository.delete(userRepository.findByName("AAA")); // 測試findAll, 查詢所有記錄, 驗證上面的刪除是否成功 Assert.assertEquals(9, userRepository.findAll().size()); }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java不用循環(huán)語句打印數(shù)組元素的實例
下面小編就為大家?guī)硪黄猨ava不用循環(huán)語句打印數(shù)組元素的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03JavaBean和SpringBean的區(qū)別及創(chuàng)建SpringBean方式
這篇文章主要介紹了JavaBean和SpringBean的區(qū)別及創(chuàng)建SpringBean方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10SpringCloud超詳細講解微服務網(wǎng)關(guān)Gateway
這篇文章主要介紹了SpringCloud Gateway微服務網(wǎng)關(guān),負載均衡,熔斷和限流,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07java實現(xiàn)String類型和Date類型相互轉(zhuǎn)換
很多人表示,java將string類型轉(zhuǎn)為date類型不知道應該怎樣做,本文就來介紹一下java實現(xiàn)String類型和Date類型相互轉(zhuǎn)換,具有一定的參考價值,感興趣的可以了解一下2023-10-10Java中使用jaxp進行sax解析_動力節(jié)點Java學院整理
使用SAX的優(yōu)勢在于其解析速度較快,相對于DOM而言占用內(nèi)存較少。這篇文章主要介紹了Java中使用jaxp進行sax解析,需要的朋友可以參考下2017-08-08深入理解SpringMVC的參數(shù)綁定與數(shù)據(jù)響應機制
本文將深入探討SpringMVC的參數(shù)綁定方式,包括基本類型、對象、集合等類型的綁定方式,以及如何處理參數(shù)校驗和異常。同時,本文還將介紹SpringMVC的數(shù)據(jù)響應機制,包括如何返回JSON、XML等格式的數(shù)據(jù),以及如何處理文件上傳和下載。2023-06-06