package com.hib;
import jakarta.persistence.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import java.util.List;
@SpringBootApplication
public class HibApplication {
@Entity
@Table(name = "memes")
public static class Meme {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 50, nullable = false)
private String content;
public Long getId() {
return id;
}
public String getContent() {
return content;
}
}
@Service
public static class MemeService {
private final MemeRepo repo;
public MemeService(MemeRepo repo) {
this.repo = repo;
}
@Transactional
public void createMeme(Meme meme) {
repo.save(meme);
}
@Transactional
public List<Meme> getMemes() {
return repo.findAll();
}
}
@RestController
public static class MemeController {
private final MemeService service;
public MemeController(MemeService service) {
this.service = service;
}
@PostMapping("/memes")
public void createMeme(@RequestBody Meme meme) {
service.createMeme(meme);
}
@GetMapping("/memes")
public List<Meme> getMemes() {
return service.getMemes();
}
}
public static void main(String[] args) {
SpringApplication.run(HibApplication.class, args);
}
}
package com.hib;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MemeRepo extends JpaRepository<HibApplication.Meme, Long> {
}
신기하게도 작동을 잘한다. 예시를 올리거나 실험을 할 때 유용할거 같다.
JPA는 spec상 argument를 안받는 protected거나 public인 constructor가 필요하다. 근데 그럼 이 코드는 왜 작동하는 걸까?
@Entity
@Table(name = "memes")
public static class Meme {
private Meme() {}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 50, nullable = false)
private String content;
public Long getId() {
return id;
}
public String getContent() {
return content;
}
}
@Entity가 Lombok처럼 생성자를 만들어준다는 얘기도 들었지만 그건 사실이 아닌거 같다. 우리가 private Meme() {} 으로 public이나 protected인 생성자가 만들어지는 것을 막았으니까.
실제로 DB에 query를 쏘는 hibernate 소스코드에 setAccessible(true)를 찾아보면 꽤 많은 군데에서 이사람들이 OOP의 기본원칙을 위반하는 것을 볼 수 있다 :D.
내 추측이지만 hibernate가 private이든 아니든 상관없이 constructor가 있으면 불러서 entity객체를 만드는 거 같다.