SpringBoot-SpringData-JPA整合
資料庫訪問這一層 常用的方式有:JdbcTemplate ,SpringData-JPA, MyBatis
今天我們說一下SpringData-JPA, 使用上一篇SpringBoot-JUnit作為基礎程式碼
注:本文使用的例子來自DD程式設計師,旨在學習,為了防止爭議,本文改為轉載
Spring-data-jpa的優勢
開發中對資料庫的操作大多為增刪改查,開發者重複大量且枯燥的程式碼來實現這部分邏輯
Spring-data-jpa使資料訪問層變成只是一層介面的編寫方式
Spring-data-jpa 只需要一個繼承了JpaRepository的介面就能實現資料的訪問
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);
}
專案結構
SpringBoot整合SpringData-JPA依賴
在pom.xml中新增依賴(以MySql資料庫為例):
<!-- SpringData-Jpa依賴-->
<dependency
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql驅動:com.mysql.jdbc.Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId >
<version>5.1.29</version>
</dependency>
資料庫連線配置
application.xml中配置資料庫連線資訊,自動建立表結構設定
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop
Spring-data-jpa依賴於Hibernate
spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置屬性
主要作用是:自動建立、更新、驗證資料庫表結構
引數配置介紹:
create:
每次載入hibernate時都會刪除上一次的生成的表,
然後根據model類重新生成表,哪怕沒有改變,
這是導致資料庫表資料丟失的一個重要原因。
create-drop:
每次載入hibernate時根據model類生成表,但sessionFactory關閉時,表自動刪除。
update:最常用
首次載入hibernate時根據model類自動建立起表結構(要先建立資料庫)
以後載入hibernate時根據model類自動更新表結構,即使表結構變了,老資料不刪除。
注意:當部署到伺服器後,表結構不會立即建立起來,應用首次執行後才會建立表結構。
validate:
每次載入hibernate時,驗證建立資料庫表結構,和資料庫表比較,不建立新表,會插入新值。
建立domain
建立User實體,會被對映到資料庫
根據配置項 hibernate.hbm2ddl.auto,應用啟動時自動建立表
import javax.persistence.*;
@Entity
public class User {
// 沒有預設構造會報錯
public User(){
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
建立資料訪問介面(原DAO層)
一般的,對於資料訪問層,需要建立一個介面來規定對資料操作的一系列方法,再建立DAO來實現此介面,從而實現對資料庫的訪問
而Spring-data-jpa,對資料訪問,只需繼承Spring-data-jpa提供的介面(這裡以JpaRepository為例)即可完成對資料的訪問
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);
}
以上即可實現資料庫的訪問,無需再寫實現類
先發一個截圖說明一下SpringData-JPA介面(後續會詳細說明)
這裡的JpaRepository介面實現的資料庫操作方法
@NoRepositoryBean
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAll(Iterable<ID> var1);
<S extends T> List<S> save(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
}
SpringData特性-通過解析方法名建立查詢
public interface UserRepository extends JpaRepository<User, Long> {
User findByName(String name);
User findByNameAndAge(String name, Integer age);
}
以上查詢使用者的兩個方法,沒有寫任何Sql,僅在介面層就完成了資料庫查詢動作
這是SpringData-JPA的一個特性-通過解析方法名建立查詢
除了解析方法名建立查詢,還提供註解建立查詢(@Query)
只需寫JPQL語句,通過類似“:name”對映@Param指定的引數即可
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);// 引數name 對映到資料庫欄位name
}
當然,SpringData-JPA給開發者帶來的便利遠不止以上這寫,這裡暫時只介紹SpringData-JPA的整合
單元測試
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void test() throws Exception {
// 建立測試資料
userRepository.save(new User(“Test1", 10));
userRepository.save(new User("Test2", 20));
userRepository.save(new User("Test3", 30));
userRepository.save(new User("Test4", 40));
userRepository.save(new User("Test5", 50));
// 測試findAll, 查詢所有記錄
Assert.assertEquals(5, userRepository.findAll().size());
// 測試findByName, 查詢姓名為Test2的User.Age=20
Assert.assertEquals(20, userRepository.findByName("Test2").getAge().longValue());
// 測試findUser, 查詢姓名為Test3的User.Age=30
Assert.assertEquals(30, userRepository.findUser("Test3").getAge().longValue());
// 測試findByNameAndAge, 查詢姓名為Test4並且年齡為40的User
Assert.assertEquals("Test4", userRepository.findByNameAndAge("Test4", 40).getName());
// 測試刪除姓名為Test5的User
userRepository.delete(userRepository.findByName("Test5"));
// 測試findAll, 刪除後為4條記錄
Assert.assertEquals(4, userRepository.findAll().size());
}
}
測試結果:
SpringBoot後續連載展望
至此SpringData的整合已經完成,後續計劃陸續更新SpringData相關文章,如:
建立表,一對多和多對一對映以及懶載入等問題
SpringData介面繼承關係和作用
各種註解的作用,如:更新操作,事務等
操作資料庫方法的規範,自己寫SQL的方式
SpringData多資料來源的實現
目前只想到這些相關的,也是專案中必知必會的
後面先繼續更新SpringBoot,上面的相關知識隨著用到進行連載
程式碼下載
維護記錄:
20170427:
修改描述錯誤: 遍歷->便利
修改@Query註解建立查詢-程式碼段錯誤