iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 12
2
Modern Web

30天學習Spring MVC系列 第 12

Day12-Spring Boot-什麼是Spring Data JPA

前言

上一章我們有介紹了使用傳統的JDBC去存取我們的資料庫,這樣做的缺點是我們在開發一項功能時我們就要撰寫一次的SQL語法,也會導致了我們DAO內的程式變成一個巨獸級的程式,當你有接過專案看過一個DAO內的class要存取資料庫做查詢的語法時你就會瞬間的崩潰了.
就此ORM(Object-Relational Mapping)的技術就誕生了,ORM利用了Model數據層與數據訪問層做了關聯,利用數據層的名稱直接與資料表名稱互相對應的連結起來,大部分情況我們程式存取數據庫只是在做CRUD的(新增,修改,刪除,讀取)這四樣操作而已,那像是hibernate與jpa的技術就這樣誕生了,他幫我們解決了利用程式對資料庫做這些的操作,讓我們更換資料庫時不需要在重寫一次程式碼,

相關ORM的概念你可以參考這篇文章(http://www.cnblogs.com/xiaowuzi/p/3485302.html )他對ORM做了非常詳述的解釋

什麼是Spring Data JPA(Java Persistence API)

介紹Spring Data JPA的原因是Spring Boot推薦使用Spring Data JPA去做ORM 持久層,原因是Spring框架
對JPA的支持度是非常的完美的,他有分頁,排序等其他的功能,可以利用程式就辦到了

我們先來介紹如何使用Spring Data JPA

Pom.xml配置

加入spring-boot-starter-data-jpa依賴

    <dependency>
        <groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-jpa</artifactId>
	</dependency>

建立一個Model
我建立一個與上個文章使用的Model名稱不同,你可以依照個人的喜好去做命名
@Entity的Bean是告訴Spring這是數據模型層的宣告

@Table name: Table的name對映到資料庫中的資料表名稱

@Column name: 對應到Table的欄位中的欄位名稱

@Id : 是此資料表的Primary Key

@GeneratedValue : 告訴此Column的生成方式 ,如果設定成GenerationType.AUTO讓容器來自動產生

還有其他的註解用法

詳細用法你可以參照官方文件做設計如下網址
(https://docs.spring.io/spring-data/jpa/docs/current/reference/html/ )
這是Spring-Data JPA相關文件

程式碼如下圖:

package com.tutorial.Model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "memberaccountjpa")
public class MemberAccountJPA {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private int id;
  @Column(name="EMAIL")
  private String email;
  @Column(name="CELLPHONE")
  private String cellphone;
  @Column(name="PASSWORD")
  private String password;
  @Column(name="ADDRESS")
  private String address;
  
  

  public int getId() {
	return id;
  }
  public void setId(int id) {
	this.id = id;
  }
  public String getEmail() {
	return email;
  }
  public void setEmail(String email) {
	this.email = email;
  }
  public String getCellphone() {
	return cellphone;
  }
  public void setCellphone(String cellphone) {
	this.cellphone = cellphone;
  }
  public String getPassword() {
	return password;
  }
  public void setPassword(String password) {
	this.password = password;
  }
  public String getAddress() {
	return address;
  }
  public void setAddress(String address) {
	this.address = address;
  }
 
  
  
  
}

在DAO Package建立一個MemberRepository類

這是一個interface並非是一個Class
我們要讓此interface繼承JpaRepository

程式碼如下

package com.tutorial.Dao;

import java.util.List;

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

import com.tutorial.Model.MemberAccountJPA;

public interface MemberRepository  extends JpaRepository<MemberAccountJPA, Long>{
	List<MemberAccountJPA> findAll();
	
	List<MemberAccountJPA> findByEmail(String email);

}

Controller修改

package com.tutorial.Controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import com.tutorial.Dao.MemberRepository;
import com.tutorial.Model.MemberAccountJPA;

@Controller
public class MemberController {
	//透過 @RequestMapping 指定從/會被對應到此addMemberPage()方法
//	@Autowired
//	MemberAccount memberAccount;
//	
//	@Autowired
//	MemberService memberService;
//	
	@Autowired
	MemberRepository memberRepository;
	
	@Autowired
	DataSource dataSource;
	 

	@GetMapping("/addMemberPage")
    public String addMemberPage(){

		List<MemberAccountJPA> memberAccountJPA= new ArrayList<MemberAccountJPA>();
		memberAccountJPA = memberRepository.findAll();

		for(int i=0;i<memberAccountJPA.size();i++){
			System.out.println(memberAccountJPA.get(i).getId());
		}
        return "addMemberPage";
    }
}

重點!!!!!

1.請在資料庫建立一個與名稱@Table(name = "memberaccountjpa") ,name字串中的資料表
2.妳可以省略@Table,但是要確保資料庫內有與此Model類別一樣名稱的資料表

application.properties

spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop

網路上的範例會加入這一行配置...請小心使用,他在程式一啟動會自動先將你的Table Drop在自動建立與Model數據定義的欄位名稱一模一樣的Table假如你的資料庫內有非常重要的資料!!!那妳就安心上路吧~~

Spring Data JPA優點

  • 可以配置多個DataSource來源
  • 多個資料表查詢
  • 可自訂SQL查詢
  • 擁有分頁與排序的功能

先想看看為何不再使用Service層?

關鍵在於Model的@Entity-的宣告與MemberRepository介面中繼承了(extends) JpaRepository<MemberAccountJPA, Long>


上一篇
Day 11-Spring Boot-如何載入靜態資源-使用thymeleaf模板引擎
下一篇
Day 13-Spring Boot-實現一個登錄功能(不含驗證)
系列文
30天學習Spring MVC30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
connor0225
iT邦新手 5 級 ‧ 2018-11-14 11:36:16

您好,
我依照您的教學執行時會發生以下ERROR,
請問是什麼原因呢?

Description:

Field memberRepository in com.example.demo.MemberController required a bean of type 'com.example.Dao.MemberRepository' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)

Action:

Consider defining a bean of type 'com.example.Dao.MemberRepository' in your configuration.

ip258852 iT邦新手 5 級 ‧ 2018-11-25 20:28:08 檢舉

沒掃到吧,在Application加入@ComponentScan

sa0124 iT邦新手 5 級 ‧ 2019-03-15 17:17:50 檢舉

我遇到一樣的問題哦,我把進入點(application)檔案往上提ㄧ個層級解決了這個問題

0
DION
iT邦新手 5 級 ‧ 2019-11-07 15:50:14

請問有沒有遇過這樣的問題?
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Nov 07 15:44:40 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).
Circular view path [addMemberPage]: would dispatch back to the current handler URL [/addMemberPage] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)

DION iT邦新手 5 級 ‧ 2019-11-07 16:43:54 檢舉

我已找到問題了調整@Controller就好了,我改@RestController

JavidHsu iT邦新手 5 級 ‧ 2019-12-11 13:30:16 檢舉

我用STS 3.9.9版是出現404

JavidHsu iT邦新手 5 級 ‧ 2019-12-16 18:56:17 檢舉

404已解決,可以參考以下的連結files所放位子
http://zetcode.com/springboot/static/

我要留言

立即登入留言