Notice
Recent Posts
Recent Comments
Link
«   2026/03   »
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
관리 메뉴

brograming

[Spring] JPA 0516 본문

Kosta

[Spring] JPA 0516

brograming 2023. 5. 16. 17:02

jpa - orm, db 자동화 프레임워크

 

 

db에서 테이블 생성 => 똑같은 이름, 컬럼명과 똑같은 멤버변수를 갖는 vo를 정의

- 애너테이션

@Entity - 테이블 클래스 정의. 지정된 vo 클래스와 동일한 이름의 테이블이 자동으로 생성되고, 이 클래스의 멤버변수와 동일한 이름과 타입의 컬럼이 생성

@Table(name="테이블명") - vo 클래스 이름과 다르게 테이블을 생성하고 싶을때 name속성에 사용할 테이블 이름 작성

@Id - 해당 컬럼을 primary key로 지정

@Column(name="컬럼명", nullalble=true/false) : 컬럼의 이름과 속성을 설정  nullalble:null을 허용할지 말지. 디폴트는 false

@Transient - 이 멤버변수는 컬럼에 제외

@PrePersist - insert문 실행전에 실행되는 메서드 지정 (sysdate 등)

 

	@Id // Primary key 지정(num)
	@SequenceGenerator(name="seq_gen",sequenceName="seq_myboard", allocationSize=1) //시퀀스 생성. allocationSize=1 시퀀스 1부터 시작
	//(generator이름, 시퀀스 이름, 시퀀스 시작 값. initialvalue=2 보통 디폴트값은 1이기 때문에 안써도 됨)
	@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seq_myboard") // 값 자동 생성 설정
	private int num;
	
	//@ManyToOne(다:일)글여러개 작성자 하나, @OneToOne(일대일)한사람이 값 하나, @OneToMany(일대다), @ManyToMany(다대다) 
	@ManyToOne
	@JoinColumn(nullable=false) //fk 설정
	@OnDelete(action = OnDeleteAction.CASCADE) // on delete cascade
	private Mymember writer;  // MyMember : entity
	
	private Date wdate;
	private String title;
	private String content;
	
	@PrePersist //insert하기 전에 날짜 먼저 생성한다.
	public void sysdate() {
		wdate = new Date();
	}

 

 

- 조인

@ManyToOne(다대일), @OneToOne(일대일) @OneToMany(일대다) @ManyToMany(다대다)

@JoinColumn(nullable=false) // fk설정

@OnDelete(action = OnDeleteAction.CASCADE  // on delete cascade

@OnDelete(action = OnDeleteAction.SETNULL

private Mymember writer;  //조인할 테이블 Entitly타입으로 선언

 

 

 

- 자동 할당

@GeneratedValue - 값을 자동 생성해서 할당. db종류에 따라서  값 할당하는 방법이 조금식 다르다

* mysql - @GeneratedValue(strategy=GenerationType.IDENTITY)     (mysql은 시퀀스를 생성하지 않는다)

* oracle - @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_myproduct")

 

=> 방법:GenerationType.IDENTITY(auto_increment)

              GenerationType.SEQUENCE(시퀀스로 할당) => 시퀀스로 값 할당하려면 먼저 시퀀스를 생성해야 함

 

=> 시퀀스 생성 : @SequenceGenerator(name="seq_gen",sequenceName="seq_myproduct", allocationSize=1)

                           sequenceName(사용할 시퀀스 이름) / allocationSize(캐쉬에 담을 값을 개수)

 

 

 

- dao 인터페이스

 

dao는 인터페이스로 만든다.

JpaRepository<Entity 클래스명, pk 타입> 인터페이스를 상속받아 만든다.

이 인터페이스의 구현은 jpa프레임워크가 자동으로 한다.

 

JpaRepository에 db작업하는 기본적인 메서드들이 선언되어 있다.

JpaRepository는 db 처리 메서드가 정의 되어 있음

* save( ) : insert, update 실행 메서드. Entity 타입의 객체를 파라미터로 받고 방금 쓰기한 한 줄을 Entity타입으로 반환

               파라미터 Entity의 pk값이 db에 없으면 insert를 실행, 있으면 update를 실행한다.

               update로 실행되면 모든 컬럼을 수정한다.

 

* findAll() : 파라미터 없다. 전체 검색한 결과를 Entity타입의 List로 반환

* findById(pk) : primary key 기준 검색. JpaRepository의< pk 타입>때문에 가능하다.

                        한줄 검색되거나 검색 안됨. 검색 안되면 예외 발생 => .orElse(null);

* deleteById(pk) : primary key 기준 한 줄 삭제. 

 

메서드 이름을 추가로 등록가능

* findBy컬럼명(컬럼타입) - 컬럼 기준 검색. 한줄이면 . Entity를, 여러줄이면 ArrayList<Entity>를 반환타입으로 지정

* findBy컬럼명 Like(컬럼타입) - like 패턴 검색

* findBy컬럼1 And 컬럼2(컬럼1타입 값1, 컬럼2타입 값2) - where 컬럼1 == 값1  and 컬럼2 == 값2

* findBy컬럼1 Or 컬럼2(컬럼1타입 값1, 컬럼2타입 값2) - where 컬럼1 == 값1  or 컬럼2 == 값2

* findBy컬럼LessThan(컬럼 타입 값) - where 컬럼 < 값

* findBy컬럼GreaterThan(컬럼 타입 값) - where 컬럼 > 값

* findBy컬럼Between(값1, 값2) - where 컬럼 between 값1 and 값2

* findBy컬럼1 OrderBy컬럼2 asc / desc(컬럼 1 타입 값1, 컬럼 2 타입 값 2) - where 컬럼1 == 값1 order by 컬럼2 desc

*조인 컬럼으로 검색: ArrayLIst<Myboard> findByWriter(Mymember writer); // 파라미터 타입은 컬럼타입과 동일해야함

 

 

 

 

▼MyProduct (db에 있는 테이블과 같다)

package com.example.demo.product;

import org.springframework.data.annotation.Transient;
import org.springframework.web.multipart.MultipartFile;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

//vo(value object) : 값 담는 객체. 
//dto(data transfer object) : 데이터를 이동시키는 객체

//dto는 기존에 쓰는 dao라고 생각하면 된다.

@Entity // 테이블 정의
@Setter
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
// @Setter, @Getter, @ToString을 @Data하나로 사용가능
public class MyProduct {
	@Id // Primary key 지정(num)
	@SequenceGenerator(name="seq_gen",sequenceName="seq_myproduct", allocationSize=1) //시퀀스 생성. allocationSize=1 시퀀스 1부터 시작
	//(generator이름, 시퀀스 이름, 시퀀스 시작 값. initialvalue=2 보통 디폴트값은 1이기 때문에 안써도 됨)
	@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seq_myproduct") // 값 자동 생성 설정
	private int num;
	
	
	private String name;
	private int price;
	private int amount;
	
//	@Transient // db 테이블에 해당 컬럼은 만들지 않는다. vo용도로는 필요하지만 db에 저장할 필요가 없을 때
//	private MultipartFile file;
}

 

 

▼application.properties

# port
server.port=8081

# JSP view
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

# oracle set
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=hr
spring.datasource.password=hr

#encoding
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true

#jpa
spring.jpa.generate-ddl=true
spring.jpa.database=oracle 
spring.jpa.show-sql=true

 

▼pom.xml

	<!-- jasper -->
		<dependency>
   			<groupId>org.apache.tomcat.embed</groupId>
   			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>
		
		<!-- jakarta -->
		<dependency>
		   <groupId>jakarta.servlet</groupId>
		   <artifactId>jakarta.servlet-api</artifactId>
		   <scope>provided</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api -->
		<dependency>
		   <groupId>jakarta.servlet.jsp.jstl</groupId>
		   <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
		   <!-- <version>3.0.0</version>-->
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl -->
		<dependency>
		   <groupId>org.glassfish.web</groupId>
		   <artifactId>jakarta.servlet.jsp.jstl</artifactId>
		   <!-- <version>3.0.1</version>-->
		</dependency>

 

▼HomeController

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {
	@RequestMapping("/")
	public String home() {
		return "index";
	}
}

 

 

▼MyProductDto

package com.example.demo.product;

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

@Setter
@Getter
@ToString
@NoArgsConstructor // 생성자
@AllArgsConstructor // 생성자
public class MyProductDto {
	private int num;
	private String name;
	private int price;
	private int amount;


}

 

▼MyProductDao

 

package com.example.demo.product;

import java.util.ArrayList;

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

@Repository
public interface ProductDao extends JpaRepository<MyProduct, Integer> { // 클래스 이름, 프라이머리 키 타입
// 인터페이스가 인터페이스를 상속받을때에는 implements가 아니라 extends이다.
	
	// JpaRepository가 기본으로 제공하지 않는 메서드는 만들어서 사용 가능
	ArrayList<MyProduct> findByName(String name);  // 제품명 정확히 일치
	ArrayList<MyProduct> findByNameLike(String name);
	ArrayList<MyProduct> findByPriceBetween(int p1, int p2);

}

 

▼ 실행하면 console에서 테이블이 생성된것을 확인할 수 있음

▼ProductDao

package com.example.demo.product;

import java.util.ArrayList;

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

@Repository
public interface ProductDao extends JpaRepository<MyProduct, Integer> { // 클래스 이름, 프라이머리 키 타입
// 인터페이스가 인터페이스를 상속받을때에는 implements가 아니라 extends이다.
	
	// JpaRepository가 기본으로 제공하지 않는 메서드는 만들어서 사용 가능
	ArrayList<MyProduct> findByName(String name);  // 제품명 정확히 일치
	ArrayList<MyProduct> findByNameLike(String name);
	ArrayList<MyProduct> findByPriceBetween(int p1, int p2);

}

 

▼ProductService

package com.example.demo.product;

import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
	@Autowired
	private ProductDao dao;
	
	public MyProductDto saveProduct(MyProductDto dto) {
		MyProduct entity = dao.save(new MyProduct(dto.getNum(), dto.getName(), dto.getPrice(), dto.getAmount()));
		MyProductDto dto2 = new MyProductDto(entity.getNum(), entity.getName(), entity.getPrice(), entity.getAmount());
		return dto2; // save = insert : 없는 pk 값이 들어오면 추가 / update: pk가 이미 db에 있으면 수정
	}
	
	public MyProductDto getProduct(int num) {
		MyProduct entity = dao.findById(num).orElse(null);
		if(entity == null) {
			return null;
		}
		
//		return dao.findById(num).orElse(null); // findById(num) : primary key기준 검색
//	//orElse(null) :  pk검색 시 검색된 것이 없으면 null반환. orElse(null) 작성하지 않으면 오류처리 해야함
		return new MyProductDto(entity.getNum(), entity.getName(), entity.getPrice(), entity.getAmount());
}
	
	public ArrayList<MyProductDto> getAll(){
		
		ArrayList<MyProduct> list = (ArrayList<MyProduct>)dao.findAll();
		ArrayList<MyProductDto> dtoList = new ArrayList<MyProductDto>();
		for(MyProduct entity:list) {
			dtoList.add(new MyProductDto(entity.getNum(),entity.getName(),entity.getPrice(),entity.getAmount()));
		}
		return dtoList; // 전체 검색
	}
	
	
	
	public void delProduct(int num) {
		dao.deleteById(num); // primary key기준 한줄 삭제
	}
	
	public ArrayList<MyProductDto> getByName(String name){
		ArrayList<MyProduct> list = (ArrayList<MyProduct>) dao.findByName(name);
		ArrayList<MyProductDto> dtoList = new ArrayList<MyProductDto>();
		for(MyProduct entity:list) {
			dtoList.add(new MyProductDto(entity.getNum(), entity.getName(), entity.getPrice(), entity.getAmount()));
		}
		return dtoList;
	}
	
	public ArrayList<MyProductDto> getByNameLike(String name){
		ArrayList<MyProduct> list = (ArrayList<MyProduct>) dao.findByNameLike(name);
		ArrayList<MyProductDto> dtoList = new ArrayList<MyProductDto>();
		for(MyProduct entity:list) {
			dtoList.add(new MyProductDto(entity.getNum(), entity.getName(), entity.getPrice(), entity.getAmount()));
		}
		return dtoList;
	}
	
	public ArrayList<MyProductDto> getByPrice(int p1, int p2){
		ArrayList<MyProduct> list = (ArrayList<MyProduct>) dao.findByPriceBetween(p1, p2);
		ArrayList<MyProductDto> dtoList = new ArrayList<MyProductDto>();
		for(MyProduct entity:list) {
			dtoList.add(new MyProductDto(entity.getNum(), entity.getName(), entity.getPrice(), entity.getAmount()));
		}
		return dtoList;
	}
}

'Kosta' 카테고리의 다른 글

토근 /cmd로 vue 프로젝트 생성_0607  (0) 2023.06.07
[Spring]05_12  (0) 2023.05.12
[Spring]05_11 jquery,ajax로 댓글달기  (0) 2023.05.11
[Spring]05_10 MemberDao.java 의존성 주입, resultmap,  (0) 2023.05.10
[Spring]05_09  (0) 2023.05.10