Spring Data JPA

一贿讹、Spring Data JPA概述

  • Java持久性API(JPA)是Java的一個(gè)規(guī)范。 它用于在Java對(duì)象和關(guān)系數(shù)據(jù)庫之間保存數(shù)據(jù)够掠。 JPA充當(dāng)面向?qū)ο蟮念I(lǐng)域模型和關(guān)系數(shù)據(jù)庫系統(tǒng)之間的橋梁民褂。
  • 由于JPA只是一個(gè)規(guī)范,它本身不執(zhí)行任何操作。 它需要一個(gè)實(shí)現(xiàn)赊堪。 因此面殖,像Hibernate,TopLink和iBatis這樣的ORM工具實(shí)現(xiàn)了JPA數(shù)據(jù)持久性規(guī)范哭廉。
  • Spring Data是Spring Framework的一部分脊僚。Spring Data存儲(chǔ)庫抽象的目標(biāo)是顯著減少為各種持久性存儲(chǔ)實(shí)現(xiàn)數(shù)據(jù)訪問層所需的代碼量。
  • Spring Data JPA不是JPA提供者遵绰。它是一個(gè)庫/框架辽幌,它在我們的JPA提供程序(如Hibernate)的頂部添加了一個(gè)額外的抽象層.其致力于減少數(shù)據(jù)訪問層(DAO)的開發(fā)量,開發(fā)者唯一要做的椿访,就只是聲明持久層的接口舶衬,其他都交給Spring Data JPA來完成。

二赎离、Spring Data JPA正向工程

  • 正向工程與逆向工程相反逛犹,即通過entity實(shí)體類生成數(shù)據(jù)庫。
  • pom.xml
    <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.44</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.0.28</version>
            </dependency>
            <!-- 添加spring-data-jpa的依賴 -->
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-jpa</artifactId>
                <version>1.11.0.RELEASE</version>
            </dependency>
            <!-- spring-data-jpa依賴于hibernate-entitymanager -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>5.2.10.Final</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>4.3.6.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.6</version>
            </dependency>
        </dependencies>
    
  • db.properties
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3307/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedSt  atements=TRUE
    user=root
    pass=123456
    
  • spring-jpa.xml
  <?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
         xmlns:jpa="http://www.springframework.org/schema/data/jpa"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
      <context:property-placeholder location="classpath:db.properties" />
      <context:component-scan base-package="com.qfedu.service" />
      <context:component-scan base-package="com.qfedu.dao" />
      <bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
          <property name="url" value="${url}" />
          <property name="driverClassName" value="${driver}" />
          <property name="username" value="${aaa}" />
          <property name="password" value="${bbb}" />
      </bean>
      <!-- 配置 HibernateJpaVendorAdapter梁剔,用來分別設(shè)置數(shù)據(jù)庫的方言和是否顯示sql語句 -->
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" id="adapter">
          <!--<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />-->
          <property name="databasePlatform" value="org.hibernate.dialect.MySQL57InnoDBDialect" />
          <property name="showSql" value="true" />
      </bean>
      <!-- 配置EntityManagerFactoryBean -->
      <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="emf">
          <property name="dataSource" ref="ds" />
          <property name="packagesToScan" value="com.qfedu.entity" />
          <property name="jpaVendorAdapter" ref="adapter" />
          <property name="jpaProperties">
              <props>
                  <prop key="hibernate.format_sql">true</prop>
                  <!--<prop key="hibernate.dialect.storage_engine">innodb</prop>-->
                  <!-- 使用hibernate.hbm2ddl.auto屬性來根據(jù)需要?jiǎng)討B(tài)創(chuàng)建數(shù)據(jù)庫的表結(jié)構(gòu)
                      create:表示啟動(dòng)的時(shí)候先drop虽画,再create
                      create-drop: 也表示創(chuàng)建,只不過再系統(tǒng)關(guān)閉前執(zhí)行一下drop
                      update: 這個(gè)操作啟動(dòng)的時(shí)候會(huì)去檢查schema是否一致荣病,如果不一致會(huì)做scheme更新
                      validate: 啟動(dòng)時(shí)驗(yàn)證現(xiàn)有schema與你配置的hibernate是否一致码撰,如果不一致就拋出異常,并不做更新 -->
                  <prop key="hibernate.hbm2ddl.auto">update</prop>
              </props>
          </property>
      </bean>
      <!-- 配置jpa的事務(wù)管理器 -->
      <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="jtx">
          <property name="entityManagerFactory" ref="emf" />
      </bean>
      <!-- 配置事務(wù)的注解驅(qū)動(dòng) -->
      <tx:annotation-driven proxy-target-class="false" transaction-manager="jtx" />
      <jpa:repositories base-package="com.qfedu.dao" entity-manager-factory-ref="emf" transaction-manager-ref="jtx" />
  </beans>
  • <prop key="hibernate.hbm2ddl.auto">update</prop>的作用是幫我們創(chuàng)建數(shù)據(jù)庫个盆。除了update還有三個(gè)值:
    • validate:加載hibernate時(shí)脖岛,驗(yàn)證創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu)
    • create:每次加載hibernate,重新創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu)颊亮,這就是導(dǎo)致數(shù)據(jù)庫表數(shù)據(jù)丟失的原因柴梆。
    • create-drop:加載hibernate時(shí)創(chuàng)建,退出時(shí)刪除表結(jié)構(gòu)
    • update:加載hibernate自動(dòng)更新數(shù)據(jù)庫結(jié)構(gòu)
    • 實(shí)際開發(fā)中一般常用validate與update终惑。

三绍在、條件查詢

  • Emp.java

    @Data
    @Entity
    @Table(name = "tbl_emp")
    public class Emp {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "eid")
        private int eid;
        /**
         * Column注解的各個(gè)屬性值說明:
         * name用來指定該屬性所對(duì)應(yīng)的列名,默認(rèn)與屬性名一致
         * unique為true代表該屬性生成的字段唯一雹有,默認(rèn)不唯一
         * nullable為false不允許為空偿渡,默認(rèn)運(yùn)行為空
         * length可以給字段指定長度,默認(rèn)為255
         */
        @Column(name = "first_name", unique = true, nullable = false, length = 20)
        private String firstName;
        @Column(name = "last_name")
        private String lastName;
        private double salary;
    }
    
  • IEmpDao.java

    @Repository
    public interface IEmpDao extends JpaRepository<Emp, Serializable> {
        List<Emp> findByFirstName(String firstName);
        List<Emp> findByLastNameAndFirstName(String lastName, String firstName);
        List<Emp> findByLastNameOrFirstName(String lastName, String firstName);
        List<Emp> findBySalaryBetween(double min, double max);
        List<Emp> findBySalaryGreaterThan(double salary);
        List<Emp> findByFirstNameLike(String first);
        List<Emp> findByLastNameOrderBySalary(String lastName);
    }
    
  • 雖然 JPA 給我們封裝好了數(shù)據(jù)庫查詢的很多方法霸奕,不需要我們手動(dòng)書寫sql語句溜宽,但是方法名有一定的規(guī)范,方法名findBy后面是必須跟屬性名相同,第一個(gè)屬性的字母不區(qū)分大小寫质帅,后面的單詞首字母要區(qū)分大小寫适揉『衔洌可以添加的關(guān)鍵字有And、Or涡扼、Like、GreaterThan盟庞、LessThan吃沪、Between、OrderBy什猖、Asc票彪、Desc、In等不狮。使用模糊查詢Like需要在字符串前后都拼接%降铸。

  • EmpServiceImpl.java

    @Service
    public class EmpServiceImpl implements IEmpService {
        JpaSpecificationExecutor d;
        @Resource
        private IEmpDao empDao;
        @Override
        public void saveEmp(Emp e) {
            empDao.saveAndFlush(e);
        }
        @Override
        public List<Emp> getEmpByFirstName(String firstname) {
            return empDao.findByFirstName(firstname);
        }
        @Override
        public List<Emp> getEmpByLastNameAndFirstName(String lastName, String firstname) {
              return empDao.findByLastNameAndFirstName(lastName, firstname);
          }
          @Override
          public List<Emp> getEmpByLastNameOrFirstName(String lastName, String firstname) {
            return empDao.findByLastNameOrFirstName(lastName, firstname);
        }
        @Override
        public List<Emp> getEmpBySalaryRange(double min, double max) {
            return empDao.findBySalaryBetween(min, max);
        }
        @Override
        public List<Emp> getEmpBySalaryGreater(double salary) {
            return empDao.findBySalaryGreaterThan(salary);
        }
        @Override
        public List<Emp> getEmpByFirstNameLike(String firstName) {
            return empDao.findByFirstNameLike(firstName);
        }
        @Override
        public List<Emp> findByLastNameOrderBySalary(String lastName) {
            return empDao.findByLastNameOrderBySalary(lastName);
        }
        @Override
        public Page<Emp> findAll(Pageable pageable) {
            return empDao.findAll(pageable);
        }
    }
    
  • EmpServiceTest.java

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:spring-jpa.xml")
    public class EmpServiceTest {
        @Resource
        private IEmpService empService;
        @Test
        public void testSaveEmp(){
            Emp e = new Emp();
            e.setFirstName("XXX");
            e.setLastName("XX");
            e.setSalary(8888);
            empService.saveEmp(e);
        }
        @Test
        public void testGetEmpsByFirstName(){
            for (Emp emp : empService.getEmpByFirstName("CCC")) {
                System.out.println(emp);
            }
        }
        @Test
        public void testGetEmpsByLastNameAndFirstName(){
            for (Emp e : empService.getEmpByLastNameOrFirstName("BBB", "BB")) {
                System.out.println(e);
            }
        }
        @Test
        public void testGetEmpBySalaryRange(){
            for (Emp emp : empService.getEmpBySalaryRange(20000, 10000)) {
                System.out.println(emp);
            }
        }
        @Test
        public void testGetEmpBySalaryGreaterThan(){
            for (Emp e : empService.getEmpBySalaryGreater(10000)) {
                System.out.println(e);
            }
        }
        @Test
        public void testGetEmpsByLike(){
            String firstName = "n";
            for (Emp emp : empService.getEmpByFirstNameLike("%" + firstName + "%")) {
                System.out.println(emp);
            }
        }
        @Test
        public void findByFirstNameOrderBySalary(){
            for (Emp e : empService.findByLastNameOrderBySalary("AAA")) {
                System.out.println(e);
            }
        }
        @Test
        public void testGetEmpsByPage(){
            Pageable pageable = new PageRequest(2, 2);
            Page<Emp> page = empService.findAll(pageable);
            List<Emp> list = page.getContent();
            for (Emp e : list) {
                System.out.println(e);
            }
        }
    }
    
  • 分頁查詢首先得到的結(jié)果是一個(gè)Page集合,然后返回的content是List集合摇零。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末推掸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子驻仅,更是在濱河造成了極大的恐慌谅畅,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件噪服,死亡現(xiàn)場離奇詭異毡泻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)粘优,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門仇味,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雹顺,你說我怎么就攤上這事丹墨。” “怎么了嬉愧?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵带到,是天一觀的道長。 經(jīng)常有香客問我英染,道長揽惹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任四康,我火速辦了婚禮搪搏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闪金。我一直安慰自己疯溺,他們只是感情好论颅,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著囱嫩,像睡著了一般恃疯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上墨闲,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天今妄,我揣著相機(jī)與錄音,去河邊找鬼鸳碧。 笑死盾鳞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瞻离。 我是一名探鬼主播腾仅,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼套利!你這毒婦竟也來了推励?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤肉迫,失蹤者是張志新(化名)和其女友劉穎吹艇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昂拂,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡受神,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了格侯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼻听。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖联四,靈堂內(nèi)的尸體忽然破棺而出撑碴,到底是詐尸還是另有隱情,我是刑警寧澤朝墩,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布醉拓,位于F島的核電站,受9級(jí)特大地震影響收苏,放射性物質(zhì)發(fā)生泄漏亿卤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一鹿霸、第九天 我趴在偏房一處隱蔽的房頂上張望排吴。 院中可真熱鬧,春花似錦懦鼠、人聲如沸钻哩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽街氢。三九已至扯键,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間珊肃,已是汗流浹背荣刑。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留近范,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓延蟹,卻偏偏與公主長得像评矩,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阱飘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容