brograming
[Spring] JPA 0516 본문
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 |