Spring Boot 使用JPA(Hibernate)操作數據庫

使用JPA(Hibernate)操作數據庫

JAP(Java Persisitence API),定義了對象關係映射(ORM)以及實體對象持久化的標準接口。

概述

在spring boot中JPA是依靠Hibernate才得以實現的。

JPA所維護的核心是實體(Entity Bean),而它是通過一個持久化上下文(Persinstence Context)來使用的。持久化上下文包含以下3個部分:

  • 對象關係映射(Object Relational Mapping,簡稱ORM,或O/RM,或O/R映射)描述,JPA支持註解或者XML兩種形式的描述,在spring boot中主要通過註解實現。
  • 實體操作API,通過規範可以實現對實體對象的CRUD操作,來完成對象的持久化和查詢。
  • 查詢語言,約定了面向對象的查詢語言JPQL(Java Persistence Query Language),通過這層關係可以實現比較靈活的查詢。

開發JPA

在Maven中引入spring-boot-starter-data-jpa

<code>        <dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-data-jpa/<artifactid>
/<dependency>/<code>

定義用戶POJO

<code>package com.lay.pojo;

//指明User是一個實體
@Entity(name = "user")
//定義映射的表

@Table(name = "t_user")
public class User {
   //表明主鍵
   @Id
   //策略為遞增
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id = null;
   
   //定義屬性和表的映射關係(屬性和數據庫列名不一致)
   @Column(name = "user_name")
   private String userName = null;
   
   //定義轉換器
   @Convert(converter = SexConverter.class)
   private SexEnum sex = null;//枚舉
   
   private String note = null;
   
   public Long getId() {
       return id;
  }
   
   public void setId(Long id) {
       this.id = id;
  }
   
   public String getUserName() {
       return userName;
  }
   
   public void setUserName(String userName) {
       this.userName = userName;
  }
   
   public SexEnum getSex() {
       return sex;
  }
   
   public void setSex(SexEnum sex) {
       this.sex = sex;
  }
   
   public String getNote() {
       return note;
  }
   

   public void setNote(String note) {
       this.note = note;
  }
   
}
​/<code>

性別枚舉類SexEnum

<code>package com.lay.enumeration;

public enum SexEnum {
   MALE(1, "男"), FEMALE(2, "女");
   
   private int id;
   
   private String name;
   
   SexEnum(int id, String name) {
       this.id = id;
       this.name = name;
  }
   
   public static SexEnum getEnumById(int id) {
       for (SexEnum sex : SexEnum.values()) {
           if (sex.getId() == id) {
               return sex;
          }
      }
       return null;
  }
   
   public static SexEnum getEnumByName(String name) {
       for (SexEnum sex : SexEnum.values()) {
           if (sex.getName().equals(name)) {
               return sex;
          }
      }
       return null;
  }
   
   public int getId() {
       return id;
  }
   
   public void setId(int id) {
       this.id = id;
  }
   
   public String getName() {

       return name;
  }
   
   public void setName(String name) {
       this.name = name;
  }
   
}
​/<code>

性別轉換器SexConverter

<code>package com.lay.converter;


public class SexConverter implements AttributeConverter<sexenum> {
   
   //將枚舉轉換為數據庫列
   @Override
   public Integer convertToDatabaseColumn(SexEnum sex) {
       return sex.getId();
  }
   
   //將數據庫列轉換為枚舉
   @Override
   public SexEnum convertToEntityAttribute(Integer id) {
       return SexEnum.getEnumById(id);
  }
   
}
​/<sexenum>/<code>


JPA接口

有了上述POJO對象的定義,我們還需要一個JPA接口來定義對應的操作。為此Spring提供了JpaRepository接口,它本身也繼承了其他接口。

JPA最頂級的接口是Repsitory,而它沒有定義任何方法,定義方法的是它的子接口CrudRepository,其定義的最基本的增刪改查操作,功能性還不足夠強大。為此PagingAndSortingRepository則繼承了它並且提供了分頁和排序的功能,最後JpaRepository擴展了PagingAndSortingRepository,而且還有QueryByExampleExecutor接口,這樣就可以擁有按例子(Example)查詢的功能,一般而言。我們只需要定義JPA擴展接口JpaRepository便可以獲得JPA提供的方法了。

JpaUserRepository

<code>package com.lay.dao;


public interface JpaUserRepository extends JpaRepository<user> {
   
}
​/<user>/<code>

這樣便擁有了系統默認幫我們實現的方法。請注意,這並不需要提供任何實現類,這些spring會根據JPA接口規範幫我們完成。

接口掃描和實體註冊

對於Jpa接口JpaUserRepository,還需要制定Spring boot的掃描路徑,才能將接口掃描到spring ioc容器中。與此同時,我們還要將實體類User的註冊給JPA才能測試這個控制器。用到兩個JPA註解:

  • @EnableJpaRepositories:啟用JPA編程
  • @EntityScan:對實體Bean掃描

啟動主函數SpringbootDatabaseApplication

<code>package com.lay;

@SpringBootApplication
//定義JPA接口掃描包路徑
@EnableJpaRepositories(basePackages = "com.lay.dao")
//定義實體Bean掃描包路徑
@EntityScan(basePackages = "com.lay.pojo")
public class SpringbootDatabaseApplication {
   
   public static void main(String[] args) {

       SpringApplication.run(SpringbootDatabaseApplication.class, args);
  }
}
​/<code>

實際上,即使沒有使用@EnableJpaRepositories和@EntityScan,只要依賴了spring-boot-starter-jpa。spring boot2.x也會對項目進行掃描。

配置文件

application.properties

<code>spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot_database
spring.datasource.username=root
spring.datasource.password=123456
# spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#指定數據連接池的類型
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
#最大等待連接中的數量,設置0為沒有限
spring.datasource.dbcp2.max-idle=10
#最大連接活動數
spring.datasource.dbcp2.max-total=50
#最大等待毫秒數,單位ms,超過時間會出錯誤信息
spring.datasource.dbcp2.max-wait-millis=10000
#數據庫連接池初始化連接數
spring.datasource.dbcp2.initial-size=5

#使用MySQL數據庫方言
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
#打印數據庫sql
spring.jpa.show-sql=true
#選擇hibernate數據定義語言(DDL)策略為update
spring.jpa.hibernate.ddl-auto=update/<code>

控制器測試接口

JpaController

<code>package com.lay.controller;

@Controller
@RequestMapping(value = "/jpa")
public class JpaController {
   
   //注入JPA接口
   @Autowired
   private JpaUserRepository jpaUserRepository = null;
   
   @RequestMapping("/getUser")
   @ResponseBody
   public User getUser(Long id) {
       //使用JPA接口查詢對象
       User user = jpaUserRepository.findById(id).get();
       return user;
       
  }
}
​/<code>

啟動服務測試,在瀏覽器地址欄輸入http://localhost:8080/jpa/getUser?id=1

日誌打印了sql

<code>Hibernate: select user0_.id as id1_0_0_, user0_.note as note2_0_0_, user0_.sex as sex3_0_0_, user0_.user_name as user_nam4_0_0_ from t_user user0_ where user0_.id=?
/<code>


使用JPA查詢語言JPQL

JPA查詢語言JPQL與Hibernate提供的HQL是十分接近的。這裡使用註解@Query標識語句就可以了。

JpaUserRepository

<code>package com.lay.dao;

public interface JpaUserRepository extends JpaRepository<user> {
   
   @Query("form user where user_name like concat('%',?1,'%')" + "and note like concat('%',?2,'%')")
   public List<user> findUsers(String userName, String note);
}

​/<user>/<user>/<code>

注意這裡寫from user中的user是定義實體類名稱(@Entity註解的name屬性),所以才能這樣定義一條JPQL,提供給上層調用。

JPA命名查詢

除了可以定義語句查詢,按照一定規則命名的方法也可以在不寫任何代碼的情況下完成邏輯。

<code>package com.lay.dao;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.lay.pojo.User;

public interface JpaUserRepository extends JpaRepository<user> {
   
   @Query("form user where user_name like concat('%',?1,'%')" + "and note like concat('%',?2,'%')")
   public List<user> findUsers(String userName, String note);
   
   /**
    * 按用戶名稱模糊查詢
    * @param userName
    * @return
    * @Date       2018年10月29日 下午4:58:07
    * @Author     lay
    */
   List<user> findByUserNameLike(String userName);
   
   /**
    * 根據主鍵查詢
    * @param id
    * @return
    * @Date       2018年10月29日 下午4:58:45
    * @Author     lay
    */
   User getUserById(Long id);

   
   /**
    * 按照用戶名稱或者備註進行模糊查詢
    * @param userName
    * @param note
    * @return
    * @Date       2018年10月29日 下午4:59:57
    * @Author     lay
    */
   List<user> findByUserNameLikeOrNoteLike(String userName, String note);
}
​/<user>/<user>/<user>/<user>/<code>

這裡的命名是以動詞(get/find)開始的,而已by代表按照什麼內容進行查詢。


分享到:


相關文章: