Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

wintertreey 님의 블로그

@MVC DB연동4 : Spring DATA JPA JpaRepository 본문

Spring

@MVC DB연동4 : Spring DATA JPA JpaRepository

wintertreey 2024. 7. 21. 14:54

프로젝트 생성시 dependencies 세팅

 

이번엔 Spring Data JPA를 추가해주었다. 


테이블 만들기 

application.properties

# JPA Hibernate setting
spring.jpa.hibernate.ddl-auto=update

기존에없던 테이블을 새로만들어줄때 적는 세팅코드.

 

update는 기존유지.

create하면 기존테이블을 drop하고 새로만듦.

 

 

 

ProductVo.java

package pack.model;

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

@Data
@Entity
@Table(name="provo")
public class ProductVo {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)//자동증가
	private int code;
	
	@Column(name="sang", nullable=false, length=20)
	private String sang;
	
	private int su;
	private int dan;
}

 

현재 데이터베이스상에는 provo, product_vo라는 이름의 테이블이 존재하지 않는다. 

properties의 설정을 통해 테이블을 생성해보고자한다. 

 

physical name provo(db에 provo라는 테이블 이름)

logical name ProductVo라는 테이블. 

 

code 칼럼은 자동증가할 수 있도록

@GeneratedValue(strategy = GenerationType.IDENTITY)

을 해주었다.

저장하면 이렇게 콘솔창에 찍히는것을 확인할 수 있다. 

 

db에 없던 테이블이 생성된다. 

 

 


package pack.model;

import java.util.List;


import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

import jakarta.persistence.Table;

public interface ProductCrudRepository extends JpaRepository<ProductVo, Integer>{
}

 

     하위                                                                           상위                        

CrudRepository > PagingAndSortingRepository > JpaRepository

 

 

앞선 글의 그림을 보았겠지만, JpaRepository가 가장 상위의 인터페이스이다. JpaRepository를 상속받으면서 ProductCrudRepository는 JpaRepository가 가진 메소드들을 자유롭게 사용할 수 있게 된다. 

package pack;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import pack.model.ProductCrudRepository;
import pack.model.ProductVo;

@SpringBootApplication
public class Sprweb14jpaApplication {

	public static void main(String[] args) {
		SpringApplication.run(Sprweb14jpaApplication.class, args)
		.getBean(Sprweb14jpaApplication.class).execute();
	}
	
	@Autowired
	ProductCrudRepository repository;
	
	private void execute() {
		System.out.println("execute");
// 이 부분에서 메소드들을 호출
	}
    
// 메소드들 ...
// 메소드들..

 

메인 메소드 뒷부분에 

.getBean(Sprweb14jpaApplication.class).execute();

부분을 통해 독립적으로 운영할 수 있게 된다.

 


자료 insert, update

private void execute() {
		insertData();
	}
    
private void insertData() {

		ProductVo productVo = new ProductVo();
		productVo.setSang("삼색펜");
		productVo.setSu(3);
		productVo.setDan(3000);
		productVo = repository.save(productVo);
		System.out.println("등록데이터: "+ productVo);
}

 

자료를 이렇게 넣어주었다. 

 

아까는 생성자로 주입. 

이번에는 세터로 주입. (생성자 어노테이션 안했음. 데이타만 있음)

 

 

private void insertData() {
		/*
		ProductVo productVo = new ProductVo();
		productVo.setSang("삼색펜");
		productVo.setSu(3);
		productVo.setDan(3000);
		productVo = repository.save(productVo);
		System.out.println("등록데이터: "+ productVo);
		*/
		
		ProductVo productVo = new ProductVo();
		productVo.setCode(1);
		productVo.setSang("지우개");
		productVo.setSu(3);
		productVo.setDan(2500);
		productVo = repository.save(productVo);
		
	}

 

 

 

추가 수정이 한 메소드에서 잘 이뤄지는걸 알 수 있다. 

 


 

 

자료읽기 - 전체, 부분

db에 자료를 추가로 넣고 읽어보자. 

 

private void selectData() {
		System.out.println("전체자료읽기: DBMS와 독립적-------");
		List<ProductVo> list = repository.findAll();//이미만들어진 메소드
		
		for(ProductVo vo:list) {
			System.out.println(vo.getCode()+ " "+vo.getSang()+ " "+vo.getSu()+ " "+vo.getDan());
		}
		
		System.out.println("부분자료 읽기----------");
		ProductVo vo = repository.findById(1).get();
		System.out.println(vo.getCode()+ " "+vo.getSang()+ " "+vo.getSu()+ " "+vo.getDan());

 


 

 

JPQL이란?


엔티티 객체를 조회하는 객체지향 쿼리로 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다. 문법은 SQL과 유사하며 간결하다. JPQL은 최종적으로 SQL로 변환된다.

JPQL은 SQL을 추상화해서 특정 데이터베이스에 의존하지 않는다는 특징이 있다. 데이터베이스 hibernate.dialect(방언)만 변경하면 JPQL을 수정하지 않아도 데이터베이스를 변경할 수 있다.

JPQL 특징
 - 테이블이 아닌 객체를 검색하는 객체지향 쿼리이다.
 - SQL을 추상화 했기 때문에 특정 DBMS 벤더에 종속적이지 않다.
 - JPA는 JPQL을 분석하여 SQL을 생성한 후 DB에서 조회한다.

 

기본 문법 

String data = "select j from Jikwon as m where j.name = '한국인'";
JPQL은 ANSI SQL과 문법이 유사하지만 몇 가지 다른 점이 있다.
1) 대소문자 구분
  엔티티와 속성은 대소문자를 구분한다. 엔티티 이름인 Jikwon , 그리고 Jikwon의 속성 name은 대소문자를 구분해줘야 한다.
  반면에 SELECT, FROM, AS 같은 JPQL 키워드는 대소문자를 구분하지 않아도 된다.
2) 엔티티 이름
  JPQL에서 사용한 Jikwon은 클래스 이름이 아닌 엔티티 이름이다. 엔티티 이름은 @Entity(name="abcd")로 설정 가능하다.
  name 속성을 생략하면 기본 값으로 클래스 이름을 사용한다.
3) 별칭
  JPQL에서 엔티티의 별칭은 필수적으로 명시해야 한다. 별칭을 명시하는 AS 키워드는 생략할 수 있다.

 


 

메소드이름으로 쿼리생성

public interface ProductCrudRepository extends JpaRepository<ProductVo, Integer>{
	
	ProductVo findByCode(Integer code);

 

메소드 이름을

find + (엔티티 이름) + By + 변수명

형태로 설정하면 "자동으로 쿼리 생성"됨. 엔티티의 이름은 생략 가능.

System.out.println("\n----- 🍒JPQL 사용🍒: 부분자료읽기(메소드이름으로 쿼리생성) -----");
		ProductVo vo3 = repository.findByCode(2);
		System.out.println(vo3.getCode()+ " "+vo3.getSang()+ " "+vo3.getSu()+ " "+vo3.getDan());

 

 

메소드임의 생성

//JPQL
	@Query(value="select p from ProductVo as p")
	List<ProductVo> findAllData();
System.out.println("----- 🍒JPQL 사용🍒: 전체자료읽기 ----- ");
		List<ProductVo> list2 = repository.findAllData();//사용자(나)가 만든 메소드
		
		for(ProductVo vo2:list2) {
			System.out.println(vo2.getCode()+ " "+vo2.getSang()+ " "+vo2.getSu()+ " "+vo2.getDan());
		}

 

 

where 조건

@Query(value = "select p from ProductVo as p where p.code=:code")
	ProductVo findByCodeMy(@Param("code") int code); //이름으로 연결
	
	@Query(value = "select p from ProductVo as p where p.code=?1")
	ProductVo findByCodeMy2(int code); //순서로 연결
	
	@Query(value = "select p from ProductVo as p where p.code=?1 or p.sang=?2")
	List<ProductVo> findByData(int code, String sang); //순서로 연결
System.out.println("----- 🍒JPQL 사용🍒: 부분자료읽기 -----");
		ProductVo vo4 = repository.findByCodeMy(1); //메소드이름 임의 생성(이름매핑)
		System.out.println(vo4.getCode()+ " "+vo4.getSang()+ " "+vo4.getSu()+ " "+vo4.getDan());
	
		ProductVo vo5 = repository.findByCodeMy2(1); //메소드이름 임의 생성(순서매핑)
		System.out.println(vo5.getCode()+ " "+vo5.getSang()+ " "+vo5.getSu()+ " "+vo5.getDan());
		
		System.out.println("\n");
		List<ProductVo> list3 = repository.findByData(3, "지우개");
		
		for(ProductVo vo6:list3) {
			System.out.println(vo6.getCode()+ " "+vo6.getSang()+ " "+vo6.getSu()+ " "+vo6.getDan());
		}

 

 

native SQL

//native Query문
	@Query(value = "select code, sang, su, dan from provo where code <= 5", nativeQuery=true)
	List<ProductVo> findAllData2();

 

 jpql문으로 감당이 안되는 복잡한경우에만 예외로 사용.

System.out.println("\n🤍🩵💙🤍🩵💙🤍🩵💙  native SQL 결과  🤍🩵💙🤍🩵💙🤍🩵💙");
		List<ProductVo> list5 = repository.findAllData2();
		for(ProductVo vo_ql:list5) {
			System.out.println(vo_ql.getCode()+ " "+vo_ql.getSang()+ " "+vo_ql.getSu()+ " "+vo_ql.getDan());
		}

 

 

 

 

 

 

 


https://cafe.daum.net/flowlife/HrhB/79

 

JPQL

JPQL이란? 엔티티 객체를 조회하는 객체지향 쿼리로 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다. 문법은 SQL과 유사하며 간결하다. JPQL은 최종적으로 SQL로 변환된

cafe.daum.net

https://kihwan95.tistory.com/5

 

Spring Data JPA(쿼리 메소드)

Spring Data JPA로 쿼리를 생성하는 방법들을 알아보겠습니다. • 메소드 이름으로 쿼리 생성 쿼리 메소드는 Repository 인터페이스에 간단한 네이밍 룰을 이용하여 메소드를 작성하면 원하는 쿼리를

kihwan95.tistory.com