SpringBoot_JPA基礎

SpringBoot_JPA基礎

  1. 創建SpringBoot工程:springboot_jpa
    java.jpg
    java.jpg

  2. 生成項目的pom文件:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>springboot_jpa</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springboot_jpa</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<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.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
  1. 添加lombok依賴
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<scope>provided</scope>
</dependency>
  1. 把application.properties改成application.yml,添加配置內容:
#數據庫連接
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    show-sql: true   #在控制檯中打印sql
  1. 數據庫表employee表結構和內容:

表結構:
在這裏插入圖片描述
主鍵id自動遞增
在這裏插入圖片描述
表內容:
在這裏插入圖片描述
6. 數據庫表department表結構和內容:

表結構:
在這裏插入圖片描述
表內容:
在這裏插入圖片描述
7. Employee實體類

package com.example.demo.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import lombok.ToString;

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Entity		//告訴JPA這是一個要和數據庫表映射的實體類
@Table(name="employee")		//用於指定和數據庫中的哪個表映射
public class Employee {
	
	@Id		//標識主鍵
	@GeneratedValue(strategy = GenerationType.IDENTITY)		//設置主鍵增長類型
	private Integer id;
	
	@Column(name = "last_name")		//指定屬性和數據庫中的哪個字段映射
	private String lastName;
	
	@Column
	private String email;
	
	@Column
	private Integer gender;
	
	@Column(name = "d_id")
	private Integer departmentId;
}
  1. EmployeeRepository接口(該接口內不需要寫任何方法)
package com.example.demo.repos;

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

import com.example.demo.entity.Employee;

/**
 * 自定義Repository,繼承JpaRepository
 * 泛型1:要處理的實體類
 * 泛型2:主鍵的類型
 * 
 * @author BLU
 */
public interface EmployeeRepository extends JpaRepository<Employee, Integer>{

}
  1. 測試類SpringbootJpaApplicationTests
package com.example.demo;

import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.example.demo.entity.Employee;
import com.example.demo.repos.EmployeeRepository;

@SpringBootTest
class SpringbootJpaApplicationTests {

	@Autowired
	EmployeeRepository er;
	
	@Test
	public void test_findbyId() {
		Optional<Employee> optional = er.findById(3);
		System.out.println(optional);
	}

}
  1. 運行test_findbyId(),控制檯打印:
Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Optional[Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)]
  1. 保存單個數據
@Test
public void test_save1() {
	Employee e = new Employee(null, "amy", "[email protected]", 2, 1);
	er.save(e);
}

控制檯打印:

Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)

數據庫增加了一條記錄:
在這裏插入圖片描述

  1. 保存多個數據
@Test
public void test_save2() {
	Employee e1 = new Employee(null, "amy1", "[email protected]", 2, 1);
	Employee e2 = new Employee(null, "amy2", "[email protected]", 2, 2);
	Employee e3 = new Employee(null, "amy3", "[email protected]", 2, 3);
	er.saveAll(Arrays.asList(e1,e2,e3));
}

控制檯打印:

Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)

數據庫增加了3條記錄:
在這裏插入圖片描述
13. 修改數據
注:添加和修改調用的都是save方法,區別是添加方法傳入的id爲空,修改方法傳入的id爲要修改的記錄的id

@Test
public void test_modify() {
	Employee e = new Employee(1, "zhangsan", "[email protected]", 2, 1);
	er.save(e);
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Hibernate: update employee set d_id=?, email=?, gender=?, last_name=? where id=?

數據庫中的第一條記錄被修改了:
在這裏插入圖片描述
14. 刪除記錄

@Test
public void test_delete() {
	er.deleteById(9);
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Hibernate: delete from employee where id=?

數據庫中的第9條記錄被刪除了
在這裏插入圖片描述
15. 查詢全部數據

@Test
public void test_findAll() {
	List<Employee> list = er.findAll();
	for(Employee e : list) {
		System.out.println(e);
	}
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=1)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
Employee(id=5, lastName=ruby, [email protected], gender=2, departmentId=3)
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=1)
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=1)
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=2)
  1. 查詢多個數據
@Test
public void test_findAllById() {
	List<Employee> list = er.findAllById(Arrays.asList(2,3,4));
	for(Employee e : list) {
		System.out.println(e);
	}
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ where employee0_.id in (? , ? , ?)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
  1. 分頁查詢 (參數0表示第1頁,參數3表示每頁的記錄個數)
@Test
public void test_page() {
	PageRequest pageRequest = PageRequest.of(0, 3);
	Page<Employee> page = er.findAll(pageRequest);
	System.out.println("totalpages"+page.getTotalPages());
	List<Employee> list = page.getContent();
	for(Employee e : list) {
		System.out.println(e);
	}
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ limit ?
Hibernate: select count(employee0_.id) as col_0_0_ from employee employee0_
totalpages3
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=1)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
  1. 排序查詢(按id和gender逆序排序)
    注:這裏Order要導入的包爲:import org.springframework.data.domain.Sort.Order;
@Test
public void test_sort() {
	Order o_id = new Order(Direction.DESC,"id");
	Order o_gender = new Order(Direction.DESC,"gender");
	Sort sort = Sort.by(o_id,o_gender);
	List<Employee> list = er.findAll(sort);
	for(Employee e : list) {
		System.out.println(e);
	}
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ order by employee0_.id desc, employee0_.gender desc
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=2)
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=1)
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=1)
Employee(id=5, lastName=ruby, [email protected], gender=2, departmentId=3)
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=1)
  1. 自定義接口EmployeeDao繼承Repository
package com.example.demo.repos;

import org.springframework.data.repository.Repository;
import com.example.demo.entity.Employee;

/**
 * 自定義Repository,繼承JpaRepository
 * 泛型1:要處理的實體類
 * 泛型2:主鍵的類型
 * 
 * @author BLU
 */
public interface EmployeeDao extends Repository<Employee, Integer>{

}
  1. 在測試類中注入EmployeeDao
@Autowired
EmployeeDao eDao;
  1. 在EmployeeDao接口中添加方法:
//根據id查詢
Employee findById(Integer id);
//根據lastName查詢
Employee findByLastName(String uname);
//模糊查詢
List<Employee> findByLastNameLike(String lastName);
  1. findById(Integer id)測試方法:
@Test
public void test_eDao_findById() {
	Employee e = eDao.findById(3);
	System.out.println(e);
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
  1. findByLastName(String uname)方法:
@Test
public void test_eDao_findByLastName() {
	Employee e = eDao.findByLastName("linda");
	System.out.println(e);
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ where employee0_.last_name=?
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
  1. findByLastNameLike(String lastName)方法:
@Test
public void test_eDao_findByLastNameLike() {
	List<Employee> list = eDao.findByLastNameLike("%amy%");
	for(Employee e : list) {
		System.out.println(e);
	}
}

控制檯打印:

Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ where employee0_.last_name like ? escape ?
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=1)
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=1)
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=2)
  1. 符合SpringData方法定義規範的寫法示例:
findByLastName
...where x.lastname = ?1

findByLastnameAndFirstname
...where x.lastname = ?1 and x.firstname = ?2

findByLastnameOrFirstname
...where x.lastname = ?1 or x.firstname = ?2 

findByIdBetween
...where x.id between ?1 and ?2

findByAgeLessThan
...where x.age < ?1

findByAgeLessThanEqual
...where x.age <= ?1

findByAgeGreaterThan
...where x.age > ?1

findByAgeGreaterThanEqual
...where x.age >= ?1

findByAgeIsNull
...where x.age is null

findByAgeIsNotNull
...where x.age not null

findByLastNameLike
...where x.lastname like ?1

findByLastNameNotLike
...where x.lastname not like ?1

findByAgeOrderByLastnameDesc
...where x.age = ?1 order by x.lastname desc

findByLastNameNot
...where x.lastname <> ?1

findByAgeIn
...where x.age in ?1

findByAgeNotIn
...where x.age not in ?1

findByActiveTrue
...where x.active = true

findByActiveFalse
...where x.active = false



級聯查詢

在上面的查詢例子中查出的Employee的departmentId結果是部門id:

Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)

而需求應該是:

Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
  1. 添加Department實體類:
package com.example.demo.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import lombok.ToString;

@Data
@ToString
@Entity
@Table(name="department")
public class Department {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Integer id;
	@Column(name = "department_name")
	private String departmentName;
	
}
  1. 修改Employee實體類的departmentId屬性:
    @Column(name = “d_id”) 註解替換爲 @JoinColumn(name = “d_id”)
    添加 @ManyToOne 註解
//@Column(name = "d_id")
@ManyToOne
@JoinColumn(name = "d_id")
private Department departmentId;
}
  1. EmployeeDao
package com.example.demo.repos;

import java.util.List;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.Repository;
import com.example.demo.entity.Employee;

public interface EmployeeDao extends Repository<Employee, Integer>{

	//根據id查詢Employee,並級聯查詢Department
	//兩表關聯,如果不指定,則默認根據id查詢的id是主表Employee的id
	Employee findById(Integer id);
	//根據Department的id查詢Employee
	//departmentId是Employee實體裏的屬性,id是Department實體裏的屬性,中間用下劃線隔開
	List<Employee> findBydepartmentId_id(Integer id);
	//模糊查詢+查詢排序(只要把方法的最後一個參數設置爲Sort就可以實現查詢結果排序)
	List<Employee> findByLastNameLike(String uname, Sort sort);
	//模糊查詢+查詢分頁(只要把方法的最後一個參數設置爲Pageable就可以實現查詢結果分頁)
	//注:Sort和Pageable都是org.springframework.data.domain包下的
	List<Employee> findByLastNameLike(String uname, Pageable pageable);
}
  1. 編寫測試方法:
package com.example.demo;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;

import com.example.demo.entity.Employee;
import com.example.demo.repos.EmployeeDao;

@SpringBootTest
class SpringbootJpaApplicationTests {
	
	@Autowired
	EmployeeDao eDao;
	
	@Test
	public void test_eDao_findbyId() {
		Employee employee = eDao.findById(3);
		System.out.println(employee);
	}
	
	@Test
	public void test_eDao_findBydepartmentId_id() {
		List<Employee> list = eDao.findBydepartmentId_id(1);
		for(Employee e : list) {
			System.out.println(e);
		}
	}
	@Test
	public void testsort_eDao_findByLastNameLike() {
		Sort sort = Sort.by(Direction.DESC, "id");
		List<Employee> list = eDao.findByLastNameLike("%amy%", sort);
		for(Employee e : list) {
			System.out.println(e);
		}
	}

	@Test
	public void testpageable_eDao_findByLastNameLike() {
		//參數0表示第1頁,參數2表示每頁兩條記錄
		PageRequest pageRequest = PageRequest.of(0, 2);
		List<Employee> list = eDao.findByLastNameLike("%amy%", pageRequest);
		for(Employee e : list) {
			System.out.println(e);
		}
	}
	
}

test_eDao_findbyId() 運行結果:

Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_, department1_.id as id1_0_1_, department1_.department_name as departme2_0_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where employee0_.id=?
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))

test_eDao_findBydepartmentId_id() 運行結果:

Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where department1_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))

testsort_eDao_findByLastNameLike() 運行結果:

Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.last_name like ? escape ? order by employee0_.id desc
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=Department(id=2, departmentName=運營部))
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))

testpageable_eDao_findByLastNameLike 運行結果:

Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.last_name like ? escape ? limit ?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))

單個排序規則寫法:

Sort sort = Sort.by(Direction.DESC, "id");
List<Employee> list = eDao.findByLastNameLike("%amy%", sort);

SQL語句:

order by employee0_.id desc

多個排序規則寫法:

Order oid = new Order(Direction.DESC, "id");
Order ogender = new Order(Direction.ASC, "gender");
Sort sort = Sort.by(oid , ogender);
List<Employee> list = eDao.findByLastNameLike("%amy%", sort);

SQL語句:

order by employee0_.id desc, employee0_.gender asc

分頁中添加排序規則的寫法:

Sort sort = Sort.by(Direction.DESC, "id");
PageRequest pageRequest = PageRequest.of(0, 2, sort);
List<Employee> list = eDao.findByLastNameLike("%amy%", pageRequest);


註解

@RepositoryDefinition

在定義Dao接口時,需要繼承Repository接口,示例如下:

public interface EmployeeDao extends Repository<Employee, Integer>{

}

可以使用 @RepositoryDefinition 註解代替上面的寫法,示例如下:

@RepositoryDefinition(domainClass=Employee.class, idClass=Integer.class)
public interface EmployeeDao{

}


@Query執行JPQL

在定義Dao接口方法時,方法名需要符合SpringData方法定義規範
使用@Query可以使方法命名擺脫JPA的規範約束,示例:

根據性別查詢Employee的Dao接口方法:

//@Query中寫的是JPQL語句,不是SQL語句
//Employee是實體類名,不是數據表名。gender是Employee實體的屬性
//佔位符 ?1 表示的是方法中的第一個參數
@Query("select e from Employee e where gender= ?1")
List<Employee> chaxunGender(Integer gender);

根據性別查詢Employee的測試方法:

@Test
public void test_eDao_chaxunGender() {
	List<Employee> list = eDao.chaxunGender(1);
	for(Employee e : list) {
		System.out.println(e);
	}
}

結果:

Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.gender=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=Department(id=2, departmentName=運營部))
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))


@Param
在上例使用@Query中自定義JPQL語句中,指定參數的方式是佔位符?1
也可以通過@Param註解指定參數的名稱。示例如下:

@Query("select e from Employee e where gender= :gender")
List<Employee> chaxunGender(@Param("gender")Integer gender);



@Query執行原生SQL

示例1:
Dao接口查詢方法:

//使用原生sql(設置nativeQuery=true)
@Query(value="select * from employee where gender = ?1", nativeQuery=true)
List<Employee> chaxunGender(Integer gender);

測試方法:

@Test
public void test_eDao_chaxunGender() {
	List<Employee> list = eDao.chaxunGender(1);
	for(Employee e : list) {
		System.out.println(e);
	}
}

結果:

Hibernate: select * from employee where gender = ?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=Department(id=2, departmentName=運營部))
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))



@Modifying註解實現修改或刪除
@Transactional事務註解保證正常執行(javax.transaction.Transactional)

修改示例:
Dao接口修改方法:

@Transactional
@Modifying
@Query("update Employee e set email = ?1 where id = ?2")
public void modifyById(String email, Integer id);

測試方法:

@Test
public void test_eDao_ModifyById() {
	eDao.modifyById("[email protected]", 1);
}

控制檯打印:

Hibernate: update employee set email=? where id=?

原數據:
在這裏插入圖片描述
運行後:
在這裏插入圖片描述
刪除示例:
Dao接口刪除方法:

@Transactional
@Modifying
@Query("delete from Employee where id = ?1")
public void deleteById(Integer id);

測試方法:

@Test
public void test_eDao_deleteById() {
	eDao.deleteById(9);
}

控制檯打印:

Hibernate: delete from employee where id=?

原數據:
在這裏插入圖片描述
執行測試後,第9條數據被刪除:
在這裏插入圖片描述



@NamedQuery註解實現單個命名查詢(javax.persistence.NamedQuery)

示例:
在Employee實體類上添加@NamedQuery註解(name指定方法名,query指定JPQL語句):

@NamedQuery(name = "Employee.findEmpByID",query = "select e from Employee e where id = ?1")

在EmployeeDao接口中聲明該方法,不需要寫任何註解。

public Employee findEmpByID(Integer id);

測試方法:

@Test
public void test_eDao_findEmpByID() {
	Employee employee = eDao.findEmpByID(3);
	System.out.println(employee);
}

運行結果:

Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))

@NamedQueries註解定義多個命名查詢的寫法:

@NamedQueries({
	@NamedQuery(name = "",query = ""),
	@NamedQuery(name = "",query = ""),
	@NamedQuery(name = "",query = ""),
	@NamedQuery(name = "",query = "")
})



@DynamicInsert
@DynamicUpdate

  1. Employee實體類加註解
@DynamicInsert(value = false)
@DynamicUpdate(value = false)
  1. 創建EmpCrudRep接口繼承CrudRepository
package com.example.demo.repos;
import org.springframework.data.repository.CrudRepository;
import com.example.demo.entity.Employee;

public interface EmpCrudRep extends CrudRepository<Employee, Integer>{
	
}
  1. 測試方法 (save方法的id爲空即表示添加方法)
@Test
public void test_empCrudRep() {
	Department dept = new Department();
	dept.setId(1);
	Employee e = new Employee(null,"jack","[email protected]",null,dept);
	empCrudRep.save(e);
}
  1. 運行結果:
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
  1. 將註解@DynamicInsert的值改爲true
@DynamicInsert(value = true)
@DynamicUpdate(value = false)
  1. 運行測試方法
@Test
public void test_empCrudRep() {
	Department dept = new Department();
	dept.setId(1);
	Employee e = new Employee(null,"jack1","[email protected]",null,dept);
	empCrudRep.save(e);
}
  1. 運行結果 (在執行insert時,只有有值的字段纔會執行insert操作,值爲null的字段不執行insert操作):
Hibernate: insert into employee (d_id, email, last_name) values (?, ?, ?)
  1. 數據:
    在這裏插入圖片描述
  2. 修改測試方法:
@Test
public void test_empCrudRep() {
	Optional<Employee> optional = empCrudRep.findById(17);
	Employee employee = optional.get();
	employee.setGender(2);
	empCrudRep.save(employee);
}
  1. sql打印:
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_, department1_.id as id1_0_1_, department1_.department_name as departme2_0_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where employee0_.id=?
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_ from employee employee0_ where employee0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: update employee set d_id=?, email=?, gender=?, last_name=? where id=?
  1. 將註解@DynamicUpdate的值改爲true
@DynamicInsert(value = true)
@DynamicUpdate(value = true)
  1. 測試方法:
@Test
public void test_empCrudRep() {	
	Optional<Employee> optional = empCrudRep.findById(18);
	Employee employee = optional.get();
	employee.setGender(2);
	empCrudRep.save(employee);
}
  1. sql打印(只有set的值才進行了update操作,未修改的字段不進行操作)
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_, department1_.id as id1_0_1_, department1_.department_name as departme2_0_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where employee0_.id=?
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_ from employee employee0_ where employee0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: update employee set gender=? where id=?
  1. 數據
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章