본문 바로가기

카테고리 없음

스프링부트 생성자주입, 세터주입을 통한 RESTful 웹서버 만들기

생성자 주입은 외부에서 생성자를 통해 의존성을 주입하는 방식으로, 객체가 생성될 때 생성자를 통해 필드를 초기화한다 초기화된 필드는 게터를 통해 속성값을 읽을 수 있고 반면에, 세터 주입은 세터 메서드를 통해 객체가 생성된 후 의존성을 수정하는 방식이다

1. Car 클래스는 @Entity 어노테이션을 사용하여 JPA 엔티티로 정의되어 있으며, 이 클래스는 데이터베이스의 테이블에 매핑, 클래스 생성자 필드들은 데이터베이스 열(columns)에 대응되어 JPA가 자동으로 관리

 

1-1.외부 클래스인 Owner 객체는 생성자 주입(Constructor Injection)을 통해 Car 객체에 주입, 이렇게 주입된 Owner는 @ManyToOne 어노테이션을 사용하여 다대일(N:1) 관계로 매핑되며, 외래 키는 데이터베이스에서 owner_id 열로 저장

 

1-2. 또한, fetch = FetchType.LAZY를 설정하여 Owner 엔티티가 실제로 필요할 때만 로딩되도록 지연 로딩을 적용해 성능을 최적화

 

 Car.class

package com.example.demo.domain;

import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.JoinColumn;

@Entity
public class Car {
	// 외래키, 다대일
	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="owner")
	private Owner owner;

	// 게터
	public Owner getOwner() {
		return owner;
	}
	
	// 세터 - 생성자를 매개변수에 넣음
	public void setOwner(Owner owner) {
		this.owner = owner;
	}
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;
	private String brand,model,color,registraionNumber;
	private int modelYear,price;
	
	public Car() {
	}
	
	// 데이터 베이스 열에 매핑
	public Car(String brand,String model,String color,String registraionNumber, int modelYear,int price, Owner owner) {
		super();
		this.brand = brand;
		this.model = model;
		this.color = color;
		this.registraionNumber = registraionNumber;
		this.modelYear = modelYear;
		this.price = price;
		this.owner = owner;
	}
	
	// 게터 세터 
	public Long getId() {
		return 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 getRegistrationNumber() {
		return registraionNumber;
	}

	public void setRegistrationNumber(String registraionNumber) {
		this.registraionNumber = registraionNumber;
	}

	public int getModelYear() {
		return modelYear;
	}

	public void setModelYear(int modelYear) {
		this.modelYear = modelYear;
	}

	public int getPrice() {
		return price;
	}

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

}

 

 

 

 

2. 일대다 관계인 Owner.class  

 

package com.example.demo.domain;

import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;

@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class Owner {
	
	// 자동차 여러개라 List<Car> 타입
	// 일대다,연쇄 업데이트,삭제 
	@JsonIgnore
	@OneToMany(cascade=CascadeType.ALL,mappedBy="owner")
	private List<Car> cars;
	
	public List<Car> getCars(){
		return cars;
	}
	
	public void setCars(List<Car> cars) {
		this.cars= cars;
	}
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Long ownerid;
	private String firstname,lastname;
	
	public Owner() {}
	
	public Owner(String firstname,String lastname) {
		super();
		this.firstname = firstname;
		this.lastname = lastname;
	}
	

	
	// 게터 - 클래스 필드의 값을 읽는 역할(재사용성 용이)
	public Long getOwnerid() {
		return ownerid;
	}
	
	public String getFistName() {
		return firstname;
	}
	
	public String getLastName() {
		return lastname;
	}
	
	// 세터 - 클래스 필드의 값을 수정하는 역할(재사용성 용이,여기성는 첫번째,마지막이름 수정)
	public void setFirstName(String firstname) {
		this.firstname = firstname;
	}
	
	public void setLastName(String lastname) {
		this.lastname = lastname;
	}
}

 

 

 

 

3. Car, Owner클래스에 JPA에 crud기능을 제공하는 스프링  CrudeRepository을 상속받아 각각의 레포지토리를 생성 

 

package com.example.demo.domain;

import org.springframework.data.repository.CrudRepository;
import java.util.List;

public interface CarRepository extends  CrudRepository<Car,Long>{
	// 브랜드조회
	List<Car> findByBrand(String brand);
	
	// 컬러조회
	List<Car> findByColor(String color);
	
	// 모델연도 조회
	List<Car> findByModelYear(int modelYear);
	
	
}
package com.example.demo.domain;

import org.springframework.data.repository.CrudRepository;

public interface OwnerRepository extends CrudRepository<Owner,Long>{

}

 

 

 

 

3-1. Restful서비스를 만들려면 따로 web 패키지를 만든 후 컨트롤러 클래스생성 그리고 @RestController,@GetMapping어노테이션 사용, 브랜드를 구체적으로 조회하고 싶으면 아래와 같이 @RequestParam을 사용한다.

 

package com.example.demo.web;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.example.demo.domain.Car;
import com.example.demo.domain.CarRepository;

@RestController
public class CarController {	
	
	
	private final CarRepository repository;
	
	public CarController(CarRepository repository){
		this.repository=repository;
	}
	
	@GetMapping("/cars")
	public Iterable<Car> getCars(){
		return repository.findAll();
	}
	
	// 브랜드로 자동차 조회
	@GetMapping("/cars/brand")
	public Iterable<Car> getCarsByBrand(@RequestParam("brand") String brand) {
	    return repository.findByBrand(brand);
	}


	
	
}

 

http://localhost:8080/cars

 

http://localhost:8080/cars/brand?brand=Nissan

 

 

4. 마지막으로 객체를 생성 후 레포지토리 saveAll()메서드로 데이터베이스에 저장한다. 로거에는 브랜드,모델을 표시한다.

 

package com.example.demo;



import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.example.demo.domain.Car;
import com.example.demo.domain.CarRepository;
import com.example.demo.domain.Owner;
import com.example.demo.domain.OwnerRepository;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
	
	private static final Logger logger =LoggerFactory.getLogger(
			DemoApplication.class);
	
	private final CarRepository repository;
	
	private final OwnerRepository ownerrepository;
	
	// 의존성 주입(생성자 매개변수)
	public DemoApplication(CarRepository repository,OwnerRepository ownerrepository) {
		this.repository = repository;
		this.ownerrepository = ownerrepository;
	}
	
			
	public static void main(String[] args) {
		
		SpringApplication.run(DemoApplication.class, args);
		
	}
	
	@Override
	public void run(String... args) throws Exception {
		
		Owner owner1 = new Owner("Hong", "Sun");
		Owner owner3 = new Owner("Luke", "Skywalker");
		ownerrepository.saveAll(Arrays.asList(owner1,owner3));
		
		repository.save(new Car("Ford", "Mustang", "Red", "ADF-1121",2023,590000, owner1));
		repository.save(new Car("Nissan", "Leaf", "White", "SSJ-3002",2020,29000,owner3));
		repository.save(new Car("Toyota", "Prius", "Silver", "KK0-0212",2022,390000,owner1));
		
		
		for(Car car:repository.findAll()) {
			logger.info("brand:{}, model:{}", car.getBrand(), car.getModel());
		}
	}

}

 

 

 

 

5. Maria 데이터베이스 

 

6. 세터주입으로 값을 수정할 수 있다(브랜드 Ford -> Kia로 변경)

 

 

 

 

 

 

참고한 책입니다 

https://www.yes24.com/product/goods/139860417

 

실전! 스프링 부트 3 & 리액트로 시작하는 모던 웹 애플리케이션 개발 - 예스24

스프링 부트와 리액트의 풍부하고 다양한 도구들을 활용해 최신 풀스택 애플리케이션 개발 비법을 배워보자!『실전! 스프링 부트 3 & 리액트로 시작하는 모던 웹 애플리케이션 개발』은 풀스택

www.yes24.com