第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Spring Boot 使用 JPA

1. 前言

使用 JDBC ,或者 JdbcTemplate 操作數(shù)據(jù)庫,需要編寫大量的 SQL 語句。SQL 語句基本都是些模板代碼,實(shí)際上是可以通過分析模板代碼的規(guī)則自動(dòng)生成的。

JPA 就是簡化 Java 持久層數(shù)據(jù)操作的技術(shù)標(biāo)準(zhǔn),是一種方案和規(guī)范。最開始是 Sun 公司提出的, Sun 公司就是開發(fā)出 Java 的公司,一度非常厲害,結(jié)果被 Oracle 收購了。Sun 公司雖然提出了 JPA 標(biāo)準(zhǔn),但是并沒有具體實(shí)現(xiàn)。JPA 的實(shí)現(xiàn)里面比較出名的就是 Hibernate 了,所以本篇我們也是以 Hibernate 實(shí)現(xiàn)為基礎(chǔ)進(jìn)行 Spring Boot + JPA 的實(shí)例講解。

本篇演示一個(gè) Spring Boot 商品管理項(xiàng)目實(shí)例,其中數(shù)據(jù)持久層操作采用 JPA ,以體會(huì) JPA 的優(yōu)雅與高效。

2. JPA 基本原理

在開始實(shí)例之前,還是有必要聊聊 JPA 是如何實(shí)現(xiàn)的,便于大家理解。

首先是 ORM 映射,通過注解或 XML 描述對(duì)象和表直接的映射關(guān)系。例如 GoodsDo 商品類對(duì)應(yīng)數(shù)據(jù)庫中的 goods 商品表,商品類里面的屬性和商品表里面的列一一對(duì)應(yīng),商品類的一個(gè)對(duì)象就對(duì)應(yīng)商品表中的一行數(shù)據(jù)。

然后就是對(duì)數(shù)據(jù)庫進(jìn)行 CRUD (增刪改查)操作了,由于已經(jīng)配置了對(duì)象和表的映射關(guān)系,所以可以自動(dòng)生成對(duì)應(yīng)的 SQL 語句,然后執(zhí)行語句即可。

3. 開發(fā)流程

光說不練那是假把式,我們來使用 Spring Boot + JPA 開發(fā)一個(gè)完整實(shí)例。

3.1 使用 Spring Initializr 創(chuàng)建項(xiàng)目

Spring Boot 版本選擇 2.2.5 ,Group 為 com.imooc , Artifact 為 spring-boot-jpa ,生成項(xiàng)目后導(dǎo)入 Eclipse 開發(fā)環(huán)境。

3.2 引入項(xiàng)目依賴

我們引入 Web 項(xiàng)目依賴、熱部署依賴。由于本項(xiàng)目需要使用 JPA 訪問數(shù)據(jù)庫,所以引入 spring-boot-starter-jdbc 、 mysql-connector-javaspring-boot-starter-data-jpa 依賴。 pom.xml 文件中依賴項(xiàng)如下:

實(shí)例:

	    <!-- 熱部署 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<!-- web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- jpa -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<!-- myql驅(qū)動(dòng) -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

3.3 修改配置文件

application.properties 中添加以下配置:

實(shí)例:

# 配置數(shù)據(jù)庫驅(qū)動(dòng)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 配置數(shù)據(jù)庫url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
# 配置數(shù)據(jù)庫用戶名
spring.datasource.username=root
# 配置數(shù)據(jù)庫密碼
spring.datasource.password=Easy@0122

# 啟動(dòng)時(shí)更新表結(jié)構(gòu),保留數(shù)據(jù)
spring.jpa.hibernate.ddl-auto=update

此處需要注意的是 spring.jpa.hibernate.ddl-auto=update 。可以理解項(xiàng)目啟動(dòng)時(shí),根據(jù)實(shí)體類結(jié)構(gòu)更新數(shù)據(jù)庫表結(jié)構(gòu),且保留數(shù)據(jù)庫中的數(shù)據(jù)。

3.4 開發(fā)商品類

開發(fā)商品類 GoodsDo ,并通過注解實(shí)現(xiàn)類結(jié)構(gòu)與數(shù)據(jù)表結(jié)構(gòu)的映射。

實(shí)例:


/**
 * 商品類
 */
@Entity // 表示這是一個(gè)數(shù)據(jù)對(duì)象類
@Table(name = "goods") // 對(duì)應(yīng)數(shù)據(jù)庫中的goods表
public class GoodsDo {
	/**
	 * 商品id
	 */
	@Id // 該字段對(duì)應(yīng)數(shù)據(jù)庫中的列為主鍵
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 主鍵自增長
	@Column(name = "id") // 對(duì)應(yīng)goods表中的id列
	private Long id;
	/**
	 * 商品名稱
	 */
	@Column(name = "name") // 對(duì)應(yīng)goods表中的name列
	private String name;
	/**
	 * 商品價(jià)格
	 */
	@Column(name = "price") // 對(duì)應(yīng)goods表中的price列
	private String price;
	/**
	 * 商品圖片
	 */
	@Column(name = "pic") // 對(duì)應(yīng)goods表中的pic列
	private String pic;
	// 省略get set方法
}

3.5 開發(fā)數(shù)據(jù)操作接口

開發(fā)商品數(shù)據(jù)接口,代碼如下:

實(shí)例:

/**
 * 商品數(shù)據(jù)操作接口
 */
@Repository
public interface IGoodsDao extends CrudRepository<GoodsDo, Long> {
}

解釋下,@Repository 將接口標(biāo)注為數(shù)據(jù)訪問層組件,該接口通過繼承 CrudRepository 實(shí)現(xiàn) CRUD 操作。泛型參數(shù)分別為實(shí)體類及主鍵的數(shù)據(jù)類型。

注意此時(shí)已經(jīng)可以通過 IGoodsDao 對(duì)數(shù)據(jù)庫 goods 表進(jìn)行增刪改查操作了。

3.6 開發(fā)服務(wù)層

開發(fā) Goods Service ,注入 IGoodsDao 類型組件實(shí)現(xiàn)服務(wù)方法。

實(shí)例:

/**
 * 商品服務(wù)類
 */
@Service
public class GoodsService {
	@Autowired
	private IGoodsDao goodsDao;

	/**
	 * 新增商品
	 */
	public void add(GoodsDo goods) {
		goodsDao.save(goods);
	}

	/**
	 * 刪除商品
	 */
	public void remove(Long id) {
		goodsDao.deleteById(id);
	}

	/**
	 * 編輯商品信息
	 */
	public void edit(GoodsDo goods) {
		goodsDao.save(goods);
	}

	/**
	 * 按id獲取商品信息
	 */
	public Optional<GoodsDo> getById(Long id) {
		return goodsDao.findById(id);
	}

	/**
	 * 獲取商品信息列表
	 */
	public Iterable<GoodsDo> getList() {
		return goodsDao.findAll();
	}
}

此處需要解釋下 Optional 類,它是一個(gè)包裝類。它的內(nèi)容是空或者包含的對(duì)象,所以可以避免空指針問題。此處稍作了解即可。

3.7 開發(fā)控制器

我們還是遵循 RESTful 風(fēng)格,開發(fā)控制器類。

實(shí)例:

/**
 * 商品控制器類
 */
@RestController
public class GoodsController {
	@Autowired
	private GoodsService goodsService;
	/**
	 * 按id獲取商品信息
	 */
	@GetMapping("/goods/{id}")
	public Optional<GoodsDo> getOne(@PathVariable("id") long id) {
		return goodsService.getById(id);
	}
	/**
	 * 獲取商品列表
	 */
	@GetMapping("/goods")
	public Iterable<GoodsDo> getList() {
		return goodsService.getList();
	}
	/**
	 * 新增商品
	 */
	@PostMapping("/goods")
	public void add(@RequestBody GoodsDo goods) {
		goodsService.add(goods);
	}
	/**
	 * 編輯商品
	 */
	@PutMapping("/goods/{id}")
	public void update(@PathVariable("id") long id, @RequestBody GoodsDo goods) {
		// 修改指定id的博客信息
		goods.setId(id);
		goodsService.edit(goods);
	}
	/**
	 * 移除商品
	 */
	@DeleteMapping("/goods/{id}")
	public void delete(@PathVariable("id") long id) {
		goodsService.remove(id);
	}
}

4. 測試

我們主要是測試 JPA 模塊正確可用,所以直接在測試類發(fā)起對(duì) IGoodsDao 方法的測試即可。

4.1 新增測試

首先我們建立數(shù)據(jù)庫 shop ,數(shù)據(jù)庫中不必有表 goods ,如果有 goods 表的話可以將它刪除。因?yàn)槲覀冊(cè)O(shè)置了 spring.jpa.hibernate.ddl-auto=update , JPA 會(huì)在項(xiàng)目啟動(dòng)時(shí)自動(dòng)建立表結(jié)構(gòu)。

實(shí)例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaAddTest {
	@Autowired
	private IGoodsDao goodsDao;

	/**
	 * 新增測試
	 */
	@Test
	public void testAdd() {
		GoodsDo goods = new GoodsDo();
		goods.setName("梨張");
		goods.setPic("梨圖片");
		goods.setPrice("2.0");
		GoodsDo result = goodsDao.save(goods);
		System.out.println("新增商品id:" + result.getId());
		assertNotNull(result);
	}
}

運(yùn)行測試類,控制臺(tái)輸出新增商品id:1,說明插入一條數(shù)據(jù)成功,且插入數(shù)據(jù) id 為 1 。

同時(shí)查看數(shù)據(jù)庫,發(fā)現(xiàn)已經(jīng)自動(dòng)構(gòu)建表結(jié)構(gòu):
圖片描述

MySQL 數(shù)據(jù)庫已自動(dòng)構(gòu)建表結(jié)構(gòu)

4.2 修改測試

當(dāng)調(diào)用 save 方法,如果給參數(shù)中 id 屬性賦值,則會(huì)進(jìn)行數(shù)據(jù)更新操作。

實(shí)例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaEditTest {
   @Autowired
   private IGoodsDao goodsDao;

   /**
    * 修改測試
    */
   @Test
   public void testEdit() {
   	GoodsDo goods = new GoodsDo();
   	goods.setId(1L);
   	goods.setName("梨張");
   	goods.setPic("梨圖片");
   	goods.setPrice("100.0");
   	GoodsDo result = goodsDao.save(goods);
   	assertNotNull(result);
   }
}

此時(shí)查看數(shù)據(jù)庫中數(shù)據(jù),發(fā)現(xiàn)金額已修改成功。
圖片描述

MySQL 數(shù)據(jù)庫中金額修改成功

4.3 查詢測試

我們進(jìn)行按 id 查詢、查詢所有操作,并打印查詢結(jié)果。

實(shí)例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaQueryTest {
   @Autowired
   private IGoodsDao goodsDao;

   /**
    * 按id查詢
    */
   @Test
   public void testQueryById() {
   	Optional<GoodsDo> goodsOptional = goodsDao.findById(1L);
   	GoodsDo goods = goodsOptional.get();
   	System.out.println(goods.getId() + "-" + goods.getName() + "-" + goods.getPic() + "-" + goods.getPrice());
   }

   /**
    * 查詢?nèi)?    */
   @Test
   public void testQueryAll() {
   	Iterable<GoodsDo> goodsIt = goodsDao.findAll();
   	for (GoodsDo goods : goodsIt) {
   		System.out.println(goods.getId() + "-" + goods.getName() + "-" + goods.getPic() + "-" + goods.getPrice());
   	}
   }
}

4.4 刪除測試

指定刪除 id 為 1 的商品。

實(shí)例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaRemoveTest {
   @Autowired
   private IGoodsDao goodsDao;

   /**
    * 刪除測試
    */
   @Test
   public void testRemove() {
   	goodsDao.deleteById(1L);
   }
}

運(yùn)行后,數(shù)據(jù)庫中商品信息被刪除,大功告成!

5. 小結(jié)

使用 JPA 后,最大的好處就是不用寫 SQL 了,完全面向?qū)ο缶幊?,簡潔又省心,何樂而不為?/p>