jdbc java,一文搞懂 Spring JPA

 2023-10-22 阅读 26 评论 0

摘要:作者 |?阿文責編 | 屠敏什么是 JPA大家好,今天我和大家聊一下關于Spring JPA 的相關知識,我們先來了解下什么是 JPA ?JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化規范。它為 Java 開發人員提供了一種對象/關聯映射工具來管理 Java 應用中

作者 |?阿文

責編 | 屠敏

什么是 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:

@Repository
public?class?UserDao?{@AutowiredJdbcTemplate?jdbcTemplate;public?int?addUser(User?user){return?jdbcTemplate.update("INSERT?INTO?t_user(username,jobs,phone)?VALUE?(?,?,?)",user.getName(),user.getJobs(),user.getPhone());}public?int?updateUser(User?user){return?jdbcTemplate.update("UPDATE?t_user?SET?username=?,jobs=?,phone=??WHERE?id=?",user.getName(),user.getJobs(),user.getPhone(),user.getId());}public?int?deleteUser(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

@Service
public?class?UserService?{@AutowiredUserDao?userDao;public?int?addUser(User?user){return?userDao.addUser(user);}public?int?updateUser(User?user){return?userDao.updateUser(user);}public?int?deleteUser(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

@Mapper
public?interface?UserMapper?{int?addUser(User?user);int?deleteUser(int?id);int?updateUser(User?user);User?getUserById(Integer?id);List<User>?getAllUsers();}

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

@Service
public?class?UserService?{@AutowiredUserMapper?userMapper;public?int?addUser(User?user){return?userMapper.addUser(user);}public?int?updateUser(User?user){return?userMapper.updateUser(user);}public?int?deleteUser(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=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.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.接下來我們建立用戶實體類

@Entity
public?class?User?{@Id@GeneratedValueprivate?long?id;@Column(nullable?=?false,?unique?=?true)private?String?userName;@Column(nullable?=?false)private?String?password;@Column(nullable?=?false)private?int?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`,如下所示

public?interface?UserRepository?extends?JpaRepository<User,?Long>?{}

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

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

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

????????……@Autowiredprivate?UserRepository?userRepository;@Test@Transactionalpublic?void?userAddTest()?{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。

@Test
public?void?testQuery()?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.我們看下下面的測試用例

@Test
public?void?testPageQuery()?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 的介紹。

【END】

更多精彩推薦
?200 個工具分析機器學習十年:前途未卜、工程師是核心!
?Python 3.9 正式版要來了,會有哪些新特性?
?零基礎編程小白如何拿 Offer?八年經驗面試官萬字肺腑之言
?無代碼開發到底是不是偽需求?
?沒了Macbook的英特爾還好嗎?
?Spring 從入門到入土——AOP 就這么簡單!| 原力計劃
?硬核!國外開發者用 25 美元做了個區塊鏈警佩相機!
你點的每個“在看”,我都認真當成了喜歡

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/161404.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息