Spring

@MVC DB연동4 : Spring DATA JPA CrudRepository

wintertreey 2024. 7. 21. 14:34

스프링 데이터 JPA : CrudRepository

Spring Data JDBC 라이브러리는 CrudRepository 인터페이스를 제공한다.
CrudRepository는 스프링 데이터 JPA에서 제공하는 기본 CRUD (Create, Read, Update, Delete) 작업을 처리하기 위한 인터페이스이다. CrudRepository는 엔티티 객체의 기본적인 데이터 조작을 간단하게 수행할 수 있도록 설계되어 있다.

 

다음은 CrudRepository의 주요 메소드

 

 

 

질문 : CrudRepository는 인터페이스인데, 예를 들어 count() 추상 메소드의 경우 count에 대한 재정의를 한 적이 없는데 어떻게 결과가 나오는 걸까?

 

CrudRepository는 스프링 데이터 JPA에서 기본 CRUD 작업을 제공하는 인터페이스.

count() 메소드와 같은 기본 메소드들은 SimpleJpaRepository와 같은 구현체에서 자동으로 제공된다.

스프링 데이터 JPA는 이 구현체를 프록시로 생성하여 실제 데이터베이스 작업을 처리해준다.

 

 

 

Spring Data JPA

 

 

 

JPA는 앞서 말했듯이 인터페이스. 즉, DB를 어떻게 사용하라고 정의한 명세의 역할을 해준다.

따라서 hibernate와 같은 구현체가 필요!

hibernate는 javax.persistence.EntityManager과 같은 인터페이스를 직접 구현한 라이브러리JPA와 Hibernate는 마치 자바의 interface해당 interface를 구현한 class와 같은 관계라고 볼 수 있다.

 

spring-data-jpa는 스프링이 제공하는 프레임워크로, 개발자가 JPA를 편하게 사용할 수 있도록 한다.

그래서 개발자가 Repository에서 findId()같은 메소드만 가져다 써도 스프링이 적합한 구현체를 만들어 bean으로 등록해준다.

 


 그렇다면 실습시작!

 

Properties 설정부터 맞춰주자.

spring.application.name=sprweb13jpa_basic

# Spring
spring.thymeleaf.prefix=classpath:templates
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false

#mariadb server connect
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://127.0.0.1:3306/gooddb
spring.datasource.username=root
spring.datasource.password=123

#jpa: hibernate setting
#Hibernate SQL 로그 레벨 설정
logging.level.org.hibernate.SQL=debug
logging.level.org.hibernate.type.descriptor.sql=trace
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect

 

spring.jpa.properties.hibernate.show_sql=true

# 실행되는 쿼리를 콘솔에 출력

spring.jpa.properties.hibernate.format_sql=true

# 콘솔에 출력되는 쿼리를 가독성좋게 변경

logging.level.org.hibernate.type.descriptor.sql=trace

#쿼리에 물음표로 출력되는 바인딩된 파라미터 출력

 

++++ 코드에는 기입하지 않았지만 추가로 기입한다.

server.servlet.context-path=/toy

이건 localhost:8080/toy/ ---

이 의미. 

 

++ properties 와 yml 의 형태비교. 같은 역할, 다른 파일. 둘 중의 한개만있으면 된다 

 


productVo.java

package pack;

import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Table(name="product") 
public class ProductVo {
	@Id
	private Integer code;
	private String sang;
	private Integer su;
	private Integer dan;
}

 

@Table(name="product")

name없으면 PRODUCT_VO가 기본이름으로 생성된다. 

 

논리적이름 Logical Name

비즈니스 로직에서 사용되는 이름.

예: ProductVo

 

물리적이름 Physical Name

db에 실제로 사용되는이름.

예: product

 

 

Integer vs int

int 기본형 primitive type Integer 래퍼 클래스 wrapper class
자동으로 기본값이 할당. int의 경우 초기값은 0 래퍼 클래스 변수는 초기값이 null. 초기화하지 않으면 null.
기본형 변수는 null 값을 가질 수 없다. 래퍼 클래스 변수는 null 값을 가질 수 있다.
메모리 사용이 적고, 스택 메모리에 저장 객체이기 때문에 힙 메모리에 저장. 더 많은 메모리를 사용.
기본형이 더 빠릅니다. 오토박싱과 언박싱이 필요 없기 때문. 오토박싱과 언박싱이 필요하기 때문에 기본형보다 느리다.

 


package pack;

import org.springframework.data.repository.CrudRepository;

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

 

 

extends CrudRepository 엔티티클라스  ,  프라이머리키타입  >  를 통해 메소드들을 지원받을 수 있다. 

그런 예로 save(), findById(), count() 등이 있다. 


 

이처럼 독립적인 프로그램으로 실행시켜보았다. 

 

상속받은 메소드들을 통해 CRUD 작업이 가능하다. 

이렇게 좌라락 지원하는 메소드들을 확인할 수 있다.

 

 

레코드 읽기 - 전체, 1개

import java.awt.geom.CubicCurve2D;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.repository.CrudRepository;

import lombok.AllArgsConstructor;
import other.OtherClass;


@SpringBootApplication
public class Sprweb13jpaBasicApplication {

	public static void main(String[] args) {
		SpringApplication.run(Sprweb13jpaBasicApplication.class, args)
		.getBean(Sprweb13jpaBasicApplication.class).myExecute();
	}
	
	@Autowired
	ProductCrudRepository crudRepository;
	
	@Autowired
	OtherClass class1;
	
	private void myExecute() {
		System.out.println("독립적인 프로그램으로 실행");
		selectData(); //목록보기

	}
    
    //레코드 읽기
	private void selectData() {
		List<ProductVo> list = (List<ProductVo>)crudRepository.findAll();
		//System.out.println(list.get(0).getSang());
		System.out.println("전체 레코드 읽기-----------------");
		for(ProductVo p:list) {
			System.out.println(p.getCode()+" "+p.getSang()+" "+p.getSu()+" "+p.getDan());
		}
		
		System.out.println("1개 레코드 읽기--------------");
	//1개 레코드 읽기
		ProductVo vo = crudRepository.findById(2).get();
		System.out.println(vo.getCode()+" "+vo.getSang()+" "+vo.getSu()+" "+vo.getDan());
		
		
	}

 

sql문을 쓰지 않고도 기본적으로 만들어져있는 메소드인 findAll()을 통해서 값을 출력할 수 있다. 

그 출력 예시가 우산.

 

이 jpa가 모든 메소드를 만들어주지않는다. 그렇다면 왜 굳이 sql문이 아닌 jpa를 사용하는걸까?

이유 : 소스코드를 바꿀 일은 없기에. ORM의 장점때문!!

 

 

레코드 추가 또는 수정

private void myExecute() {
		System.out.println("독립적인 프로그램으로 실행");	
		insdata(); //추가 또는 수정		
	}
    
    private void insdata() {
		ProductVo productVo = new ProductVo(4, "사랑비", 10, 20000);
		crudRepository.save(productVo);
	}

 

해당 내용의 소스만 가지고 왔다. 

ProductVo productVo = new ProductVo();

productVo.setCode(4);

ProductVo productVo = new ProductVo(null, "볼펜", 2, 1500);

System.out.println(productVo.toString());

 

보통 이런식으로 생성자를 선언하여 객체를 만들고 값을 넣어준다.

그러나 우리는 앞서 

productvo에서 @AllArgsConstructor로 ProductVo(Integer, String, Integer, Integer) 생성자를 만들어주었다. 

따라서 바로 값을 넣어주었다. 

 

crudRepository.save(productVo);

save가 하는일: 없는번호일경우 추가. 있는번호일경우 수정.

 

 

레코드 삭제

	private void myExecute() {
		delData(); //삭제
	}
    
    	public void delData() { 
		crudRepository.deleteById(3);
	}

 

deleteBtId

있으면 지우고, 없으면 통과. 

 

 

++ 패키지 위치

@ComponentScan

@ComponentScan(basePackages= {"other"})
public class Sprweb13jpaBasicApplication {

	public static void main(String[] args) {
		SpringApplication.run(Sprweb13jpaBasicApplication.class, args)
		.getBean(Sprweb13jpaBasicApplication.class).myExecute();
	}
	
	@Autowired
	ProductCrudRepository crudRepository;
	
	@Autowired
	OtherClass class1;
	
	private void myExecute() {
		class1.abc();
	}

 

이렇게 패키지 위치가 pack안이 아닌곳에 위치하면 읽어내질 못한다. 

 

@ComponentScan으로 해당 위치를 알려줘야 찾을 수 있다. 

 

전체 소스코드는 깃허브 sprweb13을 참고하자

https://github.com/yoonah0327/spring_source.git


https://stratosphere.tistory.com/243

 

CrudRepository 와 JpaRepository 차이.

CrudRepository 당신이 당신의 자신의 방법을 정의 할 필요없이, 갱신 및 삭제 기록을 작성 읽을 수 있도록 인터페이스는 CRUD 작업을위한 방법을 제공합니다. PagingAndSortingRepository는 엔티티 페이지 매

stratosphere.tistory.com

 

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

 

스프링 데이터 JPA : CrudRepository란?

 CrudRepository는 스프링 데이터 JPA에서 제공하는 기본 CRUD (Create, Read, Update, Delete) 작업을 처리하기 위한 인터페이스이다. CrudRepository는 엔티티 객체의 기본적인 데이터 조작을 간단하게 수행할 수

cafe.daum.net

https://tape22.tistory.com/30

 

JPA 구조는 어떻게 되어있고 spring-data-jpa와는 뭐가 다를까?

JPA는 Java Persistence API로, 자바 객체와 DB를 매핑하기 위한 인터페이스를 제공하는 자바 ORM 기술의 표준 명세입니다. SQL Mapper ORM sql과 객체를 매핑 DB와 객체를 매핑 mybatis, jdbcTemplate 등 hibernate, Eclip

tape22.tistory.com

https://mun9659.tistory.com/13

 

[스프링부트 게시판] 6. application.properties 설정

이번 게시글에서는 스프링부트의 전반적인 설정을 담당하는 application.properties 설정에 대해 설명드리려고 합니다. 먼저 .properties 에 대해서 간단히 말씀드릴 것은 'Key=Value형식으로 파라미터 정보

mun9659.tistory.com

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

 

JPA:private int nai와 private integer nai 차이는?

JPA에서 엔티티를 선언할 때 private int nai와 private integer nai는 어떤 차이가 있나요? JPA 엔티티 선언에서 private int nai와 private Integer nai는 중요한 차이점을 가지고 있습니다. 이 차

cafe.daum.net