SpringDataA 和 Mybaits 有什么區(qū)別,如何使用?
阿粉之前一直都是使用傳統(tǒng)的SSM進(jìn)行開發(fā),也就我們所說的 Spring,SpringMVC,Mybatis,即使使用的SpringBoot,無非也就是這么集中,對于持久層框架的選擇,也都是Mybaits,但是阿粉無意中發(fā)現(xiàn),現(xiàn)在使用SpringDataJPA的公司也是非常的多的,所以,今天阿粉來講一下這個SpringDataJPA.
SpringDataJPA和Mybaits
什么是JPA
jpq是面向?qū)ο蟮乃枷耄粋€對象就是一個表,強(qiáng)化的是你對這個表的控制。jpa繼承的那么多表約束注解也證明了jpa對這個數(shù)據(jù)庫對象控制很注重。
其實(shí),在阿粉的眼中,JPA好像就是和Hibernate是一樣的東西,區(qū)別并不大。
Spring Data JPA是Spring Data的子模塊。使用Spring Data,使得基于“repositories”概念的JPA實(shí)現(xiàn)更簡單和容易。Spring Data JPA的目標(biāo)是大大簡化數(shù)據(jù)訪問層代碼的編碼。作為使用者,我們只需要編寫自己的repository接口,接口中包含一些個性化的查詢方法,Spring Data JPA將自動實(shí)現(xiàn)查詢方法.
也就是說是什么呢?如果我們要寫一個根據(jù)ID查對象的方法比如:
findUserById(String Id) 首先這個方法的名稱,阿粉起名起的還是比較標(biāo)準(zhǔn)的,如果你在使用SpringDataJPA的話,再repository中直接使用這個方法名,就可以了,但是如果你使用了 Mybaits 的話,可能你需要在xml文件中,或者再方法上寫SQL 就比如這個樣子,
- select * from User where id = "xxxxx";
什么是Mybaits
mybatis則是面向sql,你的結(jié)果完全來源于sql,而對象這個東西只是用來接收sql帶來的結(jié)果集。你的一切操作都是圍繞sql,包括動態(tài)根據(jù)條件決定sql語句等。mybatis并不那么注重對象的概念。只要能接收到數(shù)據(jù)就好。
而且MyBatis對于面向?qū)ο蟮母拍顝?qiáng)調(diào)比較少,更適用于靈活的對數(shù)據(jù)進(jìn)行增、刪、改、查,所以在系統(tǒng)分析和設(shè)計(jì)過程中,要最大的發(fā)揮MyBatis的效用的話,一般使用步驟則與hibernate有所區(qū)別:
綜合整個系統(tǒng)分析出系統(tǒng)需要存儲的數(shù)據(jù)項(xiàng)目,并畫出E-R關(guān)系圖,設(shè)計(jì)表結(jié)構(gòu)
根據(jù)上一步設(shè)計(jì)的表結(jié)構(gòu),創(chuàng)建數(shù)據(jù)庫、表
編寫MyBatis的SQL 映射文件、Pojos以及數(shù)據(jù)庫操作對應(yīng)的接口方法
而且現(xiàn)在有很多的Mybaits的插件,用于逆向生成 Mybaits 的文件,比如直接通過你建立的表生成 Dao文件和 dao.xml文件。
但是今天阿粉的重點(diǎn)可不是說這個 Mybatis,而是SpringDataJPA
接下來阿粉就來詳細(xì)說說這個SpringDataJPA
什么是SpringDataJPA
官方文檔先放上
總的來說JPA是ORM規(guī)范,Hibernate是JPA規(guī)范的具體實(shí)現(xiàn),這樣的好處是開發(fā)者可以面向JPA規(guī)范進(jìn)行持久層的開發(fā),而底層的實(shí)現(xiàn)則是可以切換的。Spring Data Jpa則是在JPA之上添加另一層抽象(Repository層的實(shí)現(xiàn)),極大地簡化持久層開發(fā)及ORM框架切換的成本。
為什么這么多公司會選擇 Mybaits ,而不選擇使用 SpringDataJPA 呢?
因?yàn)镾pring Data Jpa的開發(fā)難度要大于Mybatis。主要是由于Hibernate封裝了完整的對象關(guān)系映射機(jī)制,以至于內(nèi)部的實(shí)現(xiàn)比較復(fù)雜、龐大,學(xué)習(xí)周期較長。這對于現(xiàn)在的快捷式開發(fā)顯然并不適合,但是因?yàn)槟承┕咀钤绲拈_發(fā),所以現(xiàn)在很多公司仍然延續(xù)使用 Spring Data Jpa 來進(jìn)行開發(fā),接下來阿粉就來說說這個 Spring Data Jpa 是如何使用的。
如何使用 SpringDataJPA
我們直接使用SpringBoot 整合一下Spring Data Jpa 來進(jìn)行操作。來展示如何使用 Spring Data Jpa。
創(chuàng)建一個 SpringBoot 的項(xiàng)目,
然后加入我們的依賴,或者你在創(chuàng)建的時候就進(jìn)行選擇,比如選擇好我們接下來所需要的所有依賴就像這個樣子。
這個時候我們就直接勾選上lombok,然后SpringWeb,還有我們的數(shù)據(jù)庫驅(qū)動的 Jpa 的依賴。
創(chuàng)建完成,我們就能看到已經(jīng)為我們添加好了我們所需要的依賴環(huán)境
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
如果不會選依賴的,各位,這肯定是一個非常好的方式。
接下來配置一下 yml 文件
- server:
- port: 8080
- servlet:
- context-path: /
- spring:
- datasource:
- url: jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
- username: root
- password: 123456
- jpa:
- database: MySQL
- database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
- show-sql: true
- hibernate:
- ddl-auto: update
看,最后有個hibernate,這就是之前阿粉說的,hibernate提供規(guī)范,
ddl-auto
這個參數(shù)也是有很多值的,不同的值代表著不同的內(nèi)容。
- create:每次運(yùn)行程序時,都會重新創(chuàng)建表,故而數(shù)據(jù)會丟失
- create-drop:每次運(yùn)行程序時會先創(chuàng)建表結(jié)構(gòu),然后待程序結(jié)束時清空表
- upadte:每次運(yùn)行程序,沒有表時會創(chuàng)建表,如果對象發(fā)生改變會更新表結(jié)構(gòu),原有數(shù)據(jù)不會清空,只會更新(推薦使用)
- validate:運(yùn)行程序會校驗(yàn)數(shù)據(jù)與數(shù)據(jù)庫的字段類型是否相同,字段不同會報(bào)錯
- none: 禁用DDL處理
然后啟動一下,看看是否成功,如果出現(xiàn)數(shù)據(jù)庫啥的不合適的,肯定是帳號和密碼寫錯了,或者連接的數(shù)據(jù)庫不對,看著改一下。有問題就改嘛,這才是好朋友。
看阿粉啟動的還是相對來說很成功的,接下來我們就得安排一下這個 JPa 的使用方式了。
接下來我們創(chuàng)建好一組內(nèi)容,Controller,Service,Dao,Entry,
然后是我們實(shí)體類的內(nèi)容和表
- @Data
- @Entity
- @Table(name = "user")
- public class User {
- @Id
- @GenericGenerator(name = "idGenerator", strategy = "uuid")
- @GeneratedValue(generator = "idGenerator")
- private String id;
- @Column(name = "user_name", unique = true, nullable = false, length = 64)
- private String userName;
- @Column(name = "user_password", unique = true, nullable = false, length = 64)
- private String userPassword;
- }
這時候主鍵阿粉使用的事uuid的策略,但是 Jpa 也是自帶主鍵生成策略的。
- TABLE:使用一個特定的數(shù)據(jù)庫表格來保存主鍵
- SEQUENCE:根據(jù)底層數(shù)據(jù)庫的序列來生成主鍵,條件是數(shù)據(jù)庫支持序列。這個值要與generator一起使用,generator 指定生成主鍵使用的生成器(可能是orcale中自己編寫的序列)
- IDENTITY:主鍵由數(shù)據(jù)庫自動生成(主要是支持自動增長的數(shù)據(jù)庫,如mysql)
- AUTO:主鍵由程序控制,也是GenerationType的默認(rèn)值
這時候 Dao 需要繼承一下 Jpa 的接口了。
- public interface UserDao extends JpaRepository<User, String> {}
JpaRepository里面可是自帶了不少方法的,
- List<T> findAll();
- List<T> findAll(Sort sort);
- List<T> findAllById(Iterable<ID> ids);
- <S extends T> List<S> saveAll(Iterable<S> entities);
- void flush();
- <S extends T> S saveAndFlush(S entity);
- <S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
- /** @deprecated */
- @Deprecated
- default void deleteInBatch(Iterable<T> entities) {
- this.deleteAllInBatch(entities);
- }
- void deleteAllInBatch(Iterable<T> entities);
- void deleteAllByIdInBatch(Iterable<ID> ids);
- void deleteAllInBatch();
- /** @deprecated */
- @Deprecated
- T getOne(ID id);
- T getById(ID id);
- <S extends T> List<S> findAll(Example<S> example);
- <S extends T> List<S> findAll(Example<S> example, Sort sort);
方法是真的不少,主要還是看你怎么使用,
我們來試試吧。
- @RestController
- @RequestMapping("/users")
- public class UserController {
- @Autowired
- private UserService userService;
- @RequestMapping(value = "/save")
- public User saveUser() {
- User user = new User();
- user.setUserName("zhangSan");
- user.setUserPassword("123456");
- return userService.saveUser(user);
- }
- }
Service 方法直接調(diào)用 UserDao 中的保存,也就是父類中的save方法。
- public interface UserService {
- User saveUser(User user);
- }
- @Service
- public class UserServiceImpl implements UserService {
- @Autowired
- private UserDao userDao;
- @Override
- public User saveUser(User user) {
- return userDao.save(user);
- }
- }
然后我們調(diào)用方法,再看看數(shù)據(jù)庫
我們成功插入進(jìn)去了一條數(shù)據(jù),也就是說,這個方法是沒什么毛病的呀,那是不是可以把所有的方法都挨著試一遍。
阿粉這里就不再一一的演示了,畢竟很簡單的。
如果你覺得這些方法不能夠滿足你的使用,那么你就得繼續(xù)看了,畢竟確實(shí)不能滿足日常需求呀。就比如說多參數(shù)的,查詢,這時候就有And出現(xiàn),如果有需要,你就得專門的再去 官方文檔中查看了
Jpa官方文檔
如果你想使用一下SQL語句呢?
這時候,你就得寫一個自定義的方法,然后再 Dao 你自定義方法上面加入 @Query注解然后在其中寫你的 SQL 語句。
- @Query("select * from User where u.user_password = ?1")
- User getByPassword(String password);
?1這個實(shí)際上就是代表的參數(shù),如果有多個參數(shù),可以使使用?2
其實(shí)和 Mybaits 的 #{0} 看起來很類似。
Jpa的簡單使用,你學(xué)會了么?說實(shí)在的,感覺這種方式,把代碼和SQL都融合在了一起,感覺確實(shí)不是很好,至少從觀看上面來說,體驗(yàn)就非常不好。