一)JPA簡介
Java Persistence API是一種標準技術,可讓您將對象“映射”到關係數據庫。
目前Hibernate是最流行的JPA實現之一。
優點:JPA在新增、修改、刪除操作支持非常好。大大減少了數據庫SQL的編寫。
缺點:JPA在查詢方面支持不太友好,主要是體現在多表連接查詢上,所以複雜的查詢可以用EntityManager方式。
實體類加載方式:
傳統上,JPA“實體”類在persistence.xml文件中指定。在Spring Boot中,此文件不是必需的,而是使用“實體掃描”。默認情況下,將搜索主配置類(用@EnableAutoConfiguration或註釋的一個@SpringBootApplication)下的所有軟件包。
也可以使用@EntityScan註釋來自定義實體掃描位置。
二)JPA+Mysql案例
第一步:先在Mysql數據庫創建一個表,並設置主鍵自動增長
腳本如下:
CREATE TABLE `tab_employee` (
`emp_id` int(11) UNSIGNED AUTO_INCREMENT,
`emp_name` varchar(100) DEFAULT NULL,
`emp_no` varchar(100) DEFAULT NULL,
`create_date` date DEFAULT NULL,
PRIMARY KEY (`emp_id`)
);
select * from tab_employee;
第二步:創建一個maven項目,並在pom.xml中引入SpringBoot的Jar,JPA的Jar,Mysql的Jar
pom.xml內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.oysept</groupId>
<artifactId>jpa_springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringBoot啓動類:
package com.oysept;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
}
項目結構圖如下:
第三步:創建一個application.yml配置文件,指定啓動端口和Mysql數據庫配置
注:Mysql8.0版本以上的數據庫,連接的配置有點變化,比如url後指定時區和數據庫編碼方式等。
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/oysept?serverTimezone=GMT&useUnicode=true&characterEncoding=utf8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
第四步:創建一個JPA實體類
@Entity:標識了該註解了的類,被認爲是一個典型的實體類。
@Table:標識實體類映射的數據庫表信息,name屬性,表示數據庫中的表名。
@Column:標識實體類映射的數據庫表字段信息,name屬性,表示數據庫表中的字段名。
@Id:標識一個唯一ID,常用於數據庫表主鍵字段。
@GeneratedValue:標識數據庫主鍵字段生成策略。
TABLE:使用一個特定的數據庫表來保存主鍵。
SEQUENCE:根據底層數據庫的序列來生成主鍵,條件是數據庫支持序列、Mysql好像不支持該方式。
IDENTITY:主鍵由數據庫自動生成(主要是自動增長型)。
AUTO:主鍵由程序控制,會自動匹配主鍵生成策略。
package com.oysept.bean;
import javax.persistence.*;
import java.util.Date;
/**
* 員工表
* @Table中的name屬性,表示數據庫中的表名
* @Column中的name屬性,表示數據庫表中的字段名
* @author ouyangjun
*/
@Entity
@Table(name = "TAB_EMPLOYEE")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "emp_id")
private Long empId;
@Column(name = "emp_name")
private String empName;
@Column(name = "emp_no")
private String empNO;
@Column(name = "create_date")
private Date createDate;
public Long getEmpId() {return empId;}
public void setEmpId(Long empId) {this.empId = empId;}
public String getEmpName() {return empName;}
public void setEmpName(String empName) {this.empName = empName;}
public String getEmpNO() {return empNO;}
public void setEmpNO(String empNO) {this.empNO = empNO;}
public Date getCreateDate() {return createDate;}
public void setCreateDate(Date createDate) {this.createDate = createDate;}
}
第五步:創建一個UserRepository工具類,並繼承JpaRepository接口。
JPA的功能一般是從Repository或CrudRepository接口擴展,JpaRepository接口是其子類。
並且JPA有一套自己的方法名稱命名方式,如需自定義實現,可以通過@Query註解進行擴展。
package com.oysept.repository;
import com.oysept.bean.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface UserRepository extends JpaRepository<User, Integer> {
/**
* jpa自帶分頁查詢
* @param pageable
* @return
*/
Page<User> findAll(Pageable pageable);
/**
* 根據用戶ID查詢一條數據,jpa有一定的查詢規則,以一些通用前綴開頭,比如findBy、find、get等
* 如果不想用這種默認規則,需要在接口上添加@Query主鍵,自定義實現數據查詢,如下面一個接口
* @param empId
* @return
*/
User findByEmpId(Long empId);
/**
* jpa支持對象查詢,簡稱HQL,也支持原生sql查詢
* @return
*/
@Query("select u from User u")
List<User> listUser();
// 原生sql方式查詢
@Query(value = "select emp_id as empId, emp_name as empName, emp_no as empNO, create_date as createDate from tab_employee",
nativeQuery = true)
List<User> listEmployee();
}
第六步:創建一個UserController控制器工具類,用於測試JPA接口
先創建一個空殼子,然後再一步步添加測試接口。
package com.oysept.controller;
import com.oysept.bean.User;
import com.oysept.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@RestController
public class JpaController {
@Autowired
private UserRepository userRepository;
}
方法1、新增User信息
// 新增user訪問地址: http://localhost:8080/jpa/insertUser
@RequestMapping(value="/jpa/insertUser")
public User insertUser() {
User user = new User();
user.setEmpName("aaaa");
user.setEmpNO("bbbb");
user.setCreateDate(new Date());
return userRepository.save(user);
}
方法2、批量新增User信息
// 批量新增User訪問地址: http://localhost:8080/jpa/batchInsertUser
@RequestMapping(value="/jpa/batchInsertUser")
public List<User> batchInsertUser() {
User user = null;
List<User> list = new ArrayList<User>();
for (int i=0; i<10; i++) {
user = new User();
user.setEmpName("aaaa");
user.setEmpNO("bbbb");
user.setCreateDate(new Date());
list.add(user);
}
List<User> userList = userRepository.saveAll(list);
return userList;
}
方法3、JPA自帶分頁,查詢全部用戶信息。
/**
* JPA自帶分頁,查詢全部用戶信息
* 訪問地址: http://localhost:8080/jpa/findAll
*/
@RequestMapping(value="/jpa/findAll")
public Page<User> findAll() {
Pageable pageable = Pageable.unpaged();
Page<User> page = userRepository.findAll(pageable);
return page;
}
// 自定義方式獲取全部User信息, 訪問地址: http://localhost:8080/jpa/listUser
@RequestMapping(value="/jpa/listUser")
public List<User> listUser() {
List<User> list = userRepository.listUser();
return list;
}
方法4、根據ID查詢User數據
// 根據ID查詢User數據,訪問地址: http://localhost:8080/jpa/findByEmpId
@RequestMapping(value="/jpa/findByEmpId")
public User findByEmpId() {
Long empId = 1L; // ID
User user = userRepository.findByEmpId(empId);
return user;
}
三)Table 'hibernate_sequence' doesn't exist解決方案
方案一:在application.yml或application.properties增加以下配置:
spring.jpa.properties.hibernate.hbm2ddl.auto=update
這個hibernate.hbm2ddl.auto參數的作用主要用於:自動創建、更新、驗證數據庫表結構。
有四個值:
create: 每次加載 hibernate 時都會刪除上一次的生成的表,然後根據你的 model 類再重新來生成新表,哪怕兩次沒有任何改變也要這樣執行,這就是導致數據庫表數據丟失的一個重要原因。
create-drop :每次加載 hibernate 時根據 model 類生成表,但是 sessionFactory 一關閉,表就自動刪除。
update:最常用的屬性,第一次加載 hibernate 時根據 model 類會自動建立起表的結構(前提是先建立好數據庫),以後加載 hibernate 時根據 model 類自動更新表結構,即使表結構改變了但表中的行仍然存在不會刪除以前的行。要注意的是當部署到服務器後,表結構是不會被馬上建立起來的,是要等 應用第一次運行起來後纔會。
validate :每次加載 hibernate 時,驗證創建數據庫表結構,只會和數據庫中的表進行比較,不會創建新表,但是會插入新值。
實體類配置如下:
@Id
@GeneratedValue
private Long empId;
方案二:直接在實體類中指定主鍵生成策略
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long empId;
四)JPA Repository方法名稱命名規則
方法名稱命名規則:findBy(關鍵字)+屬性名稱(屬性名稱的首字母大寫)+查詢條件(首字母大寫)
關鍵字 |
方法名 |
sql where 子句 |
---|---|---|
And |
findByNameAndPwd |
where name= ? and pwd =? |
Or |
findByNameOrSex |
where name= ? or sex=? |
Is,Equal |
findById,findByIdEquals |
where id= ? |
Between |
findByIdBetween |
where id between ? and ? |
LessThan |
findByIdLessThan |
where id < ? |
LessThanEqual |
findByIdLessThanEquals |
where id <= ? |
GreaterThan |
findByIdGreaterThan |
where id > ? |
GreaterThanEqual |
findByIdGreaterThanEquals |
where id > = ? |
After |
findByIdAfter |
where id > ? |
Before |
findByIdBefore |
where id < ? |
IsNull |
findByNameIsNull |
where name is null |
isNotNull,Not |
findByNameNotNull |
where name is not Null null |
Like |
findByNameLike |
where name like ? |
NotLike |
findByNameNotLike |
where name not like ? |
StartingWith |
findByNameStartingWith |
where name like ‘?%’ |
EndingWith |
findByNameEndingWith |
where name like ‘%?’ |
Containing |
findByNameContaining |
where name like ‘%?%’ |
OrderBy |
findByIdOrderByXDesc |
where id=? order by x desc |
Not |
findByNameNot |
where name <> ? |
In |
findByIdIn(Collection<?> c) |
where id in (?) |
NotIn |
findByIdNotIn(Collection<?> c) |
where id not in (?) |
True |
findByAaaTue |
where aaa = true |
False |
findByAaaFalse |
where aaa = false |
IgnoreCase |
findByNameIgnoreCase |
where UPPER(name)=UPPER(?) |
識別二維碼關注個人微信公衆號
本章完結,待續,歡迎轉載!
本文說明:該文章屬於原創,如需轉載,請標明文章轉載來源!