보라코딩

JPA를 이용한 데이터베이스 생성 및 접근 본문

코딩/Spring

JPA를 이용한 데이터베이스 생성 및 접근

new 보라 2023. 7. 23. 21:18
JPA 이용 + 엔티티 클래스로 데이터베이스 정의하는 방법

 

 

 

 

pom.xml

JPA와 H2 데이터베이스를 이용하려면 pom.xml 파일에 의존성을 추가한다.

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

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

 

 

 

엔티티 클래스 만들기

 

 

Car
package com.packet.cardatabase.domain;

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

@Entity
public class Car {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String brand, model, color, registerNumber;

@Column(name="`year`")
private int year;
private int price;

public Car() {};

public Car(String brand, String model, String color, String registerNumber, int year, int price) {
super();
this.brand = brand;
this.model = model;
this.color = color;
this.registerNumber = registerNumber;
this.year = year;
this.price = price;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getBrand() {
return brand;
}

public void setBrand(String brand) {
this.brand = brand;
}

public String getModel() {
return model;
}

public void setModel(String model) {
this.model = model;
}

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

public String getRegisterNumber() {
return registerNumber;
}

public void setRegisterNumber(String registerNumber) {
this.registerNumber = registerNumber;
}

public int getYear() {
return year;
}

public void setYear(int year) {
this.year = year;
}

public int getPrice() {
return price;
}

public void setPrice(int price) {
this.price = price;
}

}

 

 

 

application.properties
spring.datasource.url=jdbc:h2:meme:testdb
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

 

 

 

 

http://localhost:8080/h2-console/

 

 

 

 

 

 

 

CRUD 리포지터리 만들기

 

 

CarRepository

 

CrudRepository 인터페이스를 확장하며

<Car, Long>은 Car 엔티티 클래스의 리포지터리이고 ID 필드 형식이 Long임을 정의

package com.packet.cardatabase.domain;

import org.springframework.data.repository.CrudRepository;

public interface CarRepository extends CrudRepository<Car, Long>{

}

 

 

CardatabaseApplication

 

CommandLineRunner 인터페이스를 이용하면

애플리케이션이 완전히 시작되기 전에 추가코드 실행 가능 (예제 데이터 준비 적합)

 

package com.packet.cardatabase;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.packet.cardatabase.domain.Car;
import com.packet.cardatabase.domain.CarRepository;



@SpringBootApplication
public class CardatabaseApplication implements CommandLineRunner {

private static final Logger logger =
LoggerFactory.getLogger(CardatabaseApplication.class);

@Autowired
private CarRepository repository;

public static void main(String[] args) {
SpringApplication.run(CardatabaseApplication.class, args);
logger.info("Application started");
}

@Override
public void run(String... args) throws Exception {
repository.save(new Car("Ford", "Mustang", "Red", "ADF-1121", 2021, 59000));
repository.save(new Car("Nissan", "Leaf", "White", "SSJ-3002", 2019, 29000));
repository.save(new Car("Toyota", "Prius", "Silver", "KKO-0212", 2020, 39000));


for (Car car : repository.findAll()) {
logger.info(car.getBrand() + " " + car.getModel());
}

}
}

 

 

 

 

CarRepository

쿼리는 접두사 (findBy) 로 시작해야 한다!

다음에는 클래스 필드 나와야 한다!

 

package com.packet.cardatabase.domain;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

public interface CarRepository extends CrudRepository<Car, Long>{

// 브랜드로 자동차 검색
List<Car> findByBrand(String string);

// 색상으로 자동차 검색
List<Car> findByColor(String color);

// 연도로 자동차 검색
List<Car> findByYear(int year);

}

 

그밖에

// 브랜드와 모델로 검색
List<Car> findByBrandAndModel(String Brand, String model);

// 브랜드 또는 색상으로 검색
List<Car> findByBradnOrColor(String brand, String color);

// 쿼리 정렬
List<Car> findByBrandOrderByYearAsc(String brand);

 

 

Query 어노테이션 이용하면 SQL문으로 쿼리 생성 가능

@Query("select c from Car c where c.brand = %?1")
List<Car> findByBrand(String brand);

 

 

스프링 데이터 JPA에서 페이징 매김과 정렬 적용하고 엔티티 검색하는 메서드 제공!

public interface CarRepository extends PagingAndSortingRepository<Car, Long>

 

 

 

 

 

 

 

테이블 간의 관계 추가

 

 

일대다 관계 추가하려면

@ManyToOne  또는 @OneToMany 어노테이션 이용

 

 

 

ManyToOne

toMany의 경우, FetchType.LAZY가 기본값

toOne의 경우,  FetchType.LAZY 정의 필요

 

Eager은 즉시검색, LAZY는 지연검색

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="owner")
private Owner owner;

// getter와 setter도 추가
public Owner getOwner() {
return owner;
}

public void setOwner(Owner owner) {
this.owner = owner;
}

 

 

 

OneToMany

cascade 특성은 삭제 또는 업데이트 시 연속효과 적용되는 방법 지정

ALL은 모든 작업이 연속 적용

(소유자 삭제 시, 자동차도 모두 함께 삭제)

 

mappedBy="owner"   

    ㄴ owner 필드가 이 관계의 기본키임을 의미

 

@OneToMany(cascade = CascadeType.ALL, mappedBy="owner")
private List<Car> cars;

// getter와 setter 추가
public List<Car> getCars() {
return cars;
}

public void setCars(List<Car> cars) {
this.cars = cars;
}

 

 

 

 

CardatabaseApplication
@Override
public void run(String... args) throws Exception {

// 소유자 객체 추가하고 데이터베이스에 저장
Owner owner1 = new Owner("John", "Johnson");
Owner owner2 = new Owner("Mary", "bora");
orepository.saveAll(Arrays.asList(owner1, owner2));


repository.save(new Car("Ford", "Mustang", "Red", "ADF-1121", 2021, 59000, owner1));
repository.save(new Car("Nissan", "Leaf", "White", "SSJ-3002", 2019, 29000, owner2));
repository.save(new Car("Toyota", "Prius", "Silver", "KKO-0212", 2020, 39000, owner2));


for (Car car : repository.findAll()) {
logger.info(car.getBrand() + " " + car.getModel());
}

}

 

 

 

 

 

 

 

다대다 관계로 변경

 

 

@ManyToMany(mappedBy = "cars")
private Set<Owner> owners = new HashSet<Owner>();

public Set<Owner> getOwners() {
return owners;
}

public void setOwners(Set<Owner> owners) {
this.owners = owners;
}

 

@ManyToMany(cascade=CascadeType.PERSIST)
@JoinTable(name="car_owner",
joinColumns = {@JoinColumn(name="`id`")})
private Set<Car> cars = new HashSet<Car>();



public Set<Car> getCars() {
return cars;
}

public void setCars(Set<Car> cars) {
this.cars = cars;
}

 

 

 

car 테이블과 owner 테이블 사이에 car_owner 이라는 새 조인 테에블이 생성된다.

다대다 관계 관리하기 위해 조인테이블 사용 (@JoinTable 어노테이션)

  ㄴ 조인테이블과 조인 열의 이름 설정 가능