๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŒฟ Spring/โœ… RESTful Web Service

5. Java Persistence API ์‚ฌ์šฉ

by nitronium102 2023. 6. 20.

JPA ๊ฐœ์š”

JPA

  • Java Persistence API
  • ์ž๋ฐ” ORM ๊ธฐ์ˆ ์— ๋Œ€ํ•œ API ํ‘œ์ค€ ๋ช…์„ธ(Object Relationship Mapping)
  • ์ž๋ฐ” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • → ๋ฉ”์†Œ๋“œ ์„ ์–ธ๋ฌธ๋งŒ ์กด์žฌ. ์šฐ๋ฆฌ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐœ๋ฐœ์„ ํ•ด์•ผ ํ•œ๋‹ค ⇒ Hibernate
  • EntityManager๋ฅผ ํ†ตํ•ด CRUD ์ฒ˜๋ฆฌ

Hibernate

  • JPA์˜ ๊ตฌํ˜„์ฒด, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ⇒ JPA์˜ EntityManager๋ฅผ ๊ตฌํ˜„
  • ๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘ ํ”„๋ ˆ์ž„์›Œํฌ
  • ์ƒ์‚ฐ์„ฑ, ์œ ์ง€๋ณด์ˆ˜, ๋น„์ข…์†์„ฑ

Spring Data JPA

  • Spring Module
  • JPA๋ฅผ ์ถ”์ƒํ™”ํ•œ Repository ์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต
  • ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ ๋งŒ์œผ๋กœ๋„ Spring์—์„œ ์ œ๊ณตํ•˜๋Š” CRUD ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Spring Data JPA

JPA
Hibernate
JDBC
<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>
# jpa
spring:
  jpa:
    show-sql: true
  h2:
    console:
      enabled: true
datasource:
    url: jdbc:h2:mem:testdb // h2 1.4.200 ์ด์ƒ

→ h2 console bean์ด ๋“ฑ๋ก๋จ์„ ํ™•์ธ

 

localhost8088/h2-console → spring security์—์„œ ์„ค์ •ํ•œ ์•„์ด๋””, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ

⇒ mem(memory) : ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ธฐ๋™๋˜๋Š” ๋™์•ˆ์—๋งŒ ์œ ์ง€๋˜๋Š” db

  1. spring security ๊ธฐ๋Šฅ ์‚ญ์ œ → pom.xml์—์„œ dependency ์‚ญ์ œ ๋ฐ SpringConfig.class ์‚ญ์ œ
  2. ์‚ญ์ œ ์•ˆ ํ•˜๊ธฐ

/resource/data.sql์„ ๋งŒ๋“ค์–ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

insert into user values(1, sysdate(), 'User1', 'test1111', '701010-1111111');
insert into user values(2, sysdate(), 'User2', 'test2222', '801010-1111111');
insert into user values(3, sysdate(), 'User3', 'test3333', '901010-1111111');

๊ธฐ๋ณธ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด error๊ฐ€ ๋‚œ๋‹ค!

์Šคํ”„๋ง๋ถ€ํŠธ 2.5๋ฒ„์ „๋ถ€ํ„ฐ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ์™€ .sql ๊ฐ„์˜ ์ˆœ๋ฒˆ์— ์˜ํ•œ ์—๋Ÿฌ์ธ๋“ฏํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„์ „์ด์˜ฌ๋ผ๊ฐ€๋ฉด์„œ .sqlํŒŒ์ผ์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์กŒ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ์‹œ๋ฉด๋ฉ๋‹ˆ๋‹ค.

defer-datasource-initialization: true

jpa:
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: create
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:testdb

์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋“ค์–ด๊ฐ„ ๋ชจ์Šต

Entity ์„ค์ •

@Repository
public interfaceUserRepositoryextendsJpaRepository<User, Integer> {//์–ด๋– ํ•œ Entity๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ธ๊ฐ€,ํ•ด๋‹น entity์˜ ๊ธฐ๋ณธ ํ‚ค ํƒ€์ž…
}
@GetMapping("/users/{id}")
	public EntityModel<User> retrieveUser(@PathVariable int id){
		Optional<User> user = userRepository.findById(id);
		if (!user.isPresent())
			throw new UserNotFoundException(String.format("ID[%s] not found", id));

		// HATEOAS ์‚ฌ์šฉ
		EntityModel<User> entityModel = EntityModel.of(user.get());
		WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retreiveAllUsers());
		entityModel.add(linkTo.withRel("all-users"));

		return entityModel;
	}

H2 Console ์‚ฌ์šฉ์„ ์œ„ํ•œ SecurityConfig ํŒŒ์ผ ์ˆ˜์ •

@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/h2-console/**").permitAll();
		http.csrf().disable();
		http.headers().frameOptions().disable();
	}

JPA Service๋ฅผ ์œ„ํ•œ GET/POST/DELETE ๋ฉ”์†Œ๋“œ์ถ”๊ฐ€

Post Entity ์ถ”๊ฐ€์™€ User Entity์™€์˜ ๊ด€๊ณ„ ์„ค์ •

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {

	@Id
	@GeneratedValue
	private Integer id;

	private String description;

	// User : Post -> 1 : (0~N)
	// Main : Sub -> Parent : Child
	@ManyToOne(fetch = FetchType.LAZY)
	// ์ง€์—ฐ ๋กœ๋”ฉ : ์‚ฌ์šฉ์ž ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ๋ฅผ ํ•  ๋•Œ POST ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋กœ๋”ฉ๋˜๋Š” ๊ฒƒ x
	// post entity๊ฐ€ ์กฐํšŒ๋  ๋•Œ user entity๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒƒ!
	@JsonIgnore
	private User user;

}
@Data
@AllArgsConstructor
@NoArgsConstructor // ๋””ํดํŠธ ์ƒ์„ฑ์ž ์ƒ์„ฑ
@ApiModel(description = "์‚ฌ์šฉ์ž ์ƒ์„ธ ์ •๋ณด๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ ๊ฐ์ฒด")
@Entity
public class User {

	@Id
	@GeneratedValue
	private Integer id;

	@Size(min=2, message = "Name์€ 2๊ธ€์ž ์ด์ƒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String name;

	@Past // ๊ณผ๊ฑฐ ๋‚ ์งœ๋งŒ ๊ฐ€๋Šฅํ•œ ์ œ์•ฝ ์กฐ๊ฑด
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ๋“ฑ๋ก์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private Date joinDate;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String password;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ์ฃผ๋ฏผ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String ssn; // ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ

	@OneToMany(mappedBy = "user")
	private List<Post> posts;
}jpa:
    hibernate:
      ddl-auto: create-drop
      show-sql: true
      generate-ddl: true
      datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:testdb
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console

JPA ๊ฐœ์š”

JPA

  • Java Persistence API
  • ์ž๋ฐ” ORM ๊ธฐ์ˆ ์— ๋Œ€ํ•œ API ํ‘œ์ค€ ๋ช…์„ธ(Object Relationship Mapping)
  • ์ž๋ฐ” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • → ๋ฉ”์†Œ๋“œ ์„ ์–ธ๋ฌธ๋งŒ ์กด์žฌ. ์šฐ๋ฆฌ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐœ๋ฐœ์„ ํ•ด์•ผ ํ•œ๋‹ค ⇒ Hibernate
  • EntityManager๋ฅผ ํ†ตํ•ด CRUD ์ฒ˜๋ฆฌ

Hibernate

  • JPA์˜ ๊ตฌํ˜„์ฒด, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ⇒ JPA์˜ EntityManager๋ฅผ ๊ตฌํ˜„
  • ๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘ ํ”„๋ ˆ์ž„์›Œํฌ
  • ์ƒ์‚ฐ์„ฑ, ์œ ์ง€๋ณด์ˆ˜, ๋น„์ข…์†์„ฑ

Spring Data JPA

  • Spring Module
  • JPA๋ฅผ ์ถ”์ƒํ™”ํ•œ Repository ์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต
  • ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ ๋งŒ์œผ๋กœ๋„ Spring์—์„œ ์ œ๊ณตํ•˜๋Š” CRUD ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Spring Data JPA

JPA
Hibernate
JDBC
<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>
# jpa
spring:
  jpa:
    show-sql: true
  h2:
    console:
      enabled: true
datasource:
    url: jdbc:h2:mem:testdb // h2 1.4.200 ์ด์ƒ

→ h2 console bean์ด ๋“ฑ๋ก๋จ์„ ํ™•์ธ

localhost8088/h2-console → spring security์—์„œ ์„ค์ •ํ•œ ์•„์ด๋””, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ

⇒ mem(memory) : ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ธฐ๋™๋˜๋Š” ๋™์•ˆ์—๋งŒ ์œ ์ง€๋˜๋Š” db

  1. spring security ๊ธฐ๋Šฅ ์‚ญ์ œ → pom.xml์—์„œ dependency ์‚ญ์ œ ๋ฐ SpringConfig.class ์‚ญ์ œ
  2. ์‚ญ์ œ ์•ˆ ํ•˜๊ธฐ

/resource/data.sql์„ ๋งŒ๋“ค์–ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

insert into user values(1, sysdate(), 'User1', 'test1111', '701010-1111111');
insert into user values(2, sysdate(), 'User2', 'test2222', '801010-1111111');
insert into user values(3, sysdate(), 'User3', 'test3333', '901010-1111111');

๊ธฐ๋ณธ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด error๊ฐ€ ๋‚œ๋‹ค!

์Šคํ”„๋ง๋ถ€ํŠธ 2.5๋ฒ„์ „๋ถ€ํ„ฐ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ์™€ .sql ๊ฐ„์˜ ์ˆœ๋ฒˆ์— ์˜ํ•œ ์—๋Ÿฌ์ธ๋“ฏํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„์ „์ด์˜ฌ๋ผ๊ฐ€๋ฉด์„œ .sqlํŒŒ์ผ์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์กŒ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ์‹œ๋ฉด๋ฉ๋‹ˆ๋‹ค.

defer-datasource-initialization: true

jpa:
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: create
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:testdb

์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋“ค์–ด๊ฐ„ ๋ชจ์Šต

Entity ์„ค์ •

@Repository
public interfaceUserRepositoryextendsJpaRepository<User, Integer> {//์–ด๋– ํ•œ Entity๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ธ๊ฐ€,ํ•ด๋‹น entity์˜ ๊ธฐ๋ณธ ํ‚ค ํƒ€์ž…
}
@GetMapping("/users/{id}")
	public EntityModel<User> retrieveUser(@PathVariable int id){
		Optional<User> user = userRepository.findById(id);
		if (!user.isPresent())
			throw new UserNotFoundException(String.format("ID[%s] not found", id));

		// HATEOAS ์‚ฌ์šฉ
		EntityModel<User> entityModel = EntityModel.of(user.get());
		WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retreiveAllUsers());
		entityModel.add(linkTo.withRel("all-users"));

		return entityModel;
	}

H2 Console ์‚ฌ์šฉ์„ ์œ„ํ•œ SecurityConfig ํŒŒ์ผ ์ˆ˜์ •

@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/h2-console/**").permitAll();
		http.csrf().disable();
		http.headers().frameOptions().disable();
	}

JPA Service๋ฅผ ์œ„ํ•œ GET/POST/DELETE ๋ฉ”์†Œ๋“œ์ถ”๊ฐ€

Post Entity ์ถ”๊ฐ€์™€ User Entity์™€์˜ ๊ด€๊ณ„ ์„ค์ •

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {

	@Id
	@GeneratedValue
	private Integer id;

	private String description;

	// User : Post -> 1 : (0~N)
	// Main : Sub -> Parent : Child
	@ManyToOne(fetch = FetchType.LAZY)
	// ์ง€์—ฐ ๋กœ๋”ฉ : ์‚ฌ์šฉ์ž ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ๋ฅผ ํ•  ๋•Œ POST ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋กœ๋”ฉ๋˜๋Š” ๊ฒƒ x
	// post entity๊ฐ€ ์กฐํšŒ๋  ๋•Œ user entity๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒƒ!
	@JsonIgnore
	private User user;

}
@Data
@AllArgsConstructor
@NoArgsConstructor // ๋””ํดํŠธ ์ƒ์„ฑ์ž ์ƒ์„ฑ
@ApiModel(description = "์‚ฌ์šฉ์ž ์ƒ์„ธ ์ •๋ณด๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ ๊ฐ์ฒด")
@Entity
public class User {

	@Id
	@GeneratedValue
	private Integer id;

	@Size(min=2, message = "Name์€ 2๊ธ€์ž ์ด์ƒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String name;

	@Past // ๊ณผ๊ฑฐ ๋‚ ์งœ๋งŒ ๊ฐ€๋Šฅํ•œ ์ œ์•ฝ ์กฐ๊ฑด
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ๋“ฑ๋ก์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private Date joinDate;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String password;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ์ฃผ๋ฏผ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String ssn; // ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ

	@OneToMany(mappedBy = "user")
	private List<Post> posts;
}jpa:
    hibernate:
      ddl-auto: create-drop
      show-sql: true
      generate-ddl: true
      datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:testdb
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console

JPA ๊ฐœ์š”

JPA

  • Java Persistence API
  • ์ž๋ฐ” ORM ๊ธฐ์ˆ ์— ๋Œ€ํ•œ API ํ‘œ์ค€ ๋ช…์„ธ(Object Relationship Mapping)
  • ์ž๋ฐ” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • → ๋ฉ”์†Œ๋“œ ์„ ์–ธ๋ฌธ๋งŒ ์กด์žฌ. ์šฐ๋ฆฌ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐœ๋ฐœ์„ ํ•ด์•ผ ํ•œ๋‹ค ⇒ Hibernate
  • EntityManager๋ฅผ ํ†ตํ•ด CRUD ์ฒ˜๋ฆฌ

Hibernate

  • JPA์˜ ๊ตฌํ˜„์ฒด, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ⇒ JPA์˜ EntityManager๋ฅผ ๊ตฌํ˜„
  • ๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘ ํ”„๋ ˆ์ž„์›Œํฌ
  • ์ƒ์‚ฐ์„ฑ, ์œ ์ง€๋ณด์ˆ˜, ๋น„์ข…์†์„ฑ

Spring Data JPA

  • Spring Module
  • JPA๋ฅผ ์ถ”์ƒํ™”ํ•œ Repository ์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต
  • ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ ๋งŒ์œผ๋กœ๋„ Spring์—์„œ ์ œ๊ณตํ•˜๋Š” CRUD ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Spring Data JPA

JPA
Hibernate
JDBC
<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>
# jpa
spring:
  jpa:
    show-sql: true
  h2:
    console:
      enabled: true
datasource:
    url: jdbc:h2:mem:testdb // h2 1.4.200 ์ด์ƒ

→ h2 console bean์ด ๋“ฑ๋ก๋จ์„ ํ™•์ธ

localhost8088/h2-console → spring security์—์„œ ์„ค์ •ํ•œ ์•„์ด๋””, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ

⇒ mem(memory) : ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ธฐ๋™๋˜๋Š” ๋™์•ˆ์—๋งŒ ์œ ์ง€๋˜๋Š” db

  1. spring security ๊ธฐ๋Šฅ ์‚ญ์ œ → pom.xml์—์„œ dependency ์‚ญ์ œ ๋ฐ SpringConfig.class ์‚ญ์ œ
  2. ์‚ญ์ œ ์•ˆ ํ•˜๊ธฐ

/resource/data.sql์„ ๋งŒ๋“ค์–ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

insert into user values(1, sysdate(), 'User1', 'test1111', '701010-1111111');
insert into user values(2, sysdate(), 'User2', 'test2222', '801010-1111111');
insert into user values(3, sysdate(), 'User3', 'test3333', '901010-1111111');

๊ธฐ๋ณธ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด error๊ฐ€ ๋‚œ๋‹ค!

์Šคํ”„๋ง๋ถ€ํŠธ 2.5๋ฒ„์ „๋ถ€ํ„ฐ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ์™€ .sql ๊ฐ„์˜ ์ˆœ๋ฒˆ์— ์˜ํ•œ ์—๋Ÿฌ์ธ๋“ฏํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„์ „์ด์˜ฌ๋ผ๊ฐ€๋ฉด์„œ .sqlํŒŒ์ผ์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์กŒ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ์‹œ๋ฉด๋ฉ๋‹ˆ๋‹ค.

defer-datasource-initialization: true

jpa:
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: create
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:testdb

์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋“ค์–ด๊ฐ„ ๋ชจ์Šต

Entity ์„ค์ •

@Repository
public interfaceUserRepositoryextendsJpaRepository<User, Integer> {//์–ด๋– ํ•œ Entity๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ธ๊ฐ€,ํ•ด๋‹น entity์˜ ๊ธฐ๋ณธ ํ‚ค ํƒ€์ž…
}
@GetMapping("/users/{id}")
	public EntityModel<User> retrieveUser(@PathVariable int id){
		Optional<User> user = userRepository.findById(id);
		if (!user.isPresent())
			throw new UserNotFoundException(String.format("ID[%s] not found", id));

		// HATEOAS ์‚ฌ์šฉ
		EntityModel<User> entityModel = EntityModel.of(user.get());
		WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retreiveAllUsers());
		entityModel.add(linkTo.withRel("all-users"));

		return entityModel;
	}

H2 Console ์‚ฌ์šฉ์„ ์œ„ํ•œ SecurityConfig ํŒŒ์ผ ์ˆ˜์ •

@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/h2-console/**").permitAll();
		http.csrf().disable();
		http.headers().frameOptions().disable();
	}

JPA Service๋ฅผ ์œ„ํ•œ GET/POST/DELETE ๋ฉ”์†Œ๋“œ์ถ”๊ฐ€

Post Entity ์ถ”๊ฐ€์™€ User Entity์™€์˜ ๊ด€๊ณ„ ์„ค์ •

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {

	@Id
	@GeneratedValue
	private Integer id;

	private String description;

	// User : Post -> 1 : (0~N)
	// Main : Sub -> Parent : Child
	@ManyToOne(fetch = FetchType.LAZY)
	// ์ง€์—ฐ ๋กœ๋”ฉ : ์‚ฌ์šฉ์ž ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ๋ฅผ ํ•  ๋•Œ POST ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋กœ๋”ฉ๋˜๋Š” ๊ฒƒ x
	// post entity๊ฐ€ ์กฐํšŒ๋  ๋•Œ user entity๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒƒ!
	@JsonIgnore
	private User user;

}
@Data
@AllArgsConstructor
@NoArgsConstructor // ๋””ํดํŠธ ์ƒ์„ฑ์ž ์ƒ์„ฑ
@ApiModel(description = "์‚ฌ์šฉ์ž ์ƒ์„ธ ์ •๋ณด๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ ๊ฐ์ฒด")
@Entity
public class User {

	@Id
	@GeneratedValue
	private Integer id;

	@Size(min=2, message = "Name์€ 2๊ธ€์ž ์ด์ƒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String name;

	@Past // ๊ณผ๊ฑฐ ๋‚ ์งœ๋งŒ ๊ฐ€๋Šฅํ•œ ์ œ์•ฝ ์กฐ๊ฑด
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ๋“ฑ๋ก์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private Date joinDate;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String password;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ์ฃผ๋ฏผ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String ssn; // ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ

	@OneToMany(mappedBy = "user")
	private List<Post> posts;
}jpa:
    hibernate:
      ddl-auto: create-drop
      show-sql: true
      generate-ddl: true
      datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:testdb
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console

JPA ๊ฐœ์š”

JPA

  • Java Persistence API
  • ์ž๋ฐ” ORM ๊ธฐ์ˆ ์— ๋Œ€ํ•œ API ํ‘œ์ค€ ๋ช…์„ธ(Object Relationship Mapping)
  • ์ž๋ฐ” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • → ๋ฉ”์†Œ๋“œ ์„ ์–ธ๋ฌธ๋งŒ ์กด์žฌ. ์šฐ๋ฆฌ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐœ๋ฐœ์„ ํ•ด์•ผ ํ•œ๋‹ค ⇒ Hibernate
  • EntityManager๋ฅผ ํ†ตํ•ด CRUD ์ฒ˜๋ฆฌ

Hibernate

  • JPA์˜ ๊ตฌํ˜„์ฒด, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ⇒ JPA์˜ EntityManager๋ฅผ ๊ตฌํ˜„
  • ๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘ ํ”„๋ ˆ์ž„์›Œํฌ
  • ์ƒ์‚ฐ์„ฑ, ์œ ์ง€๋ณด์ˆ˜, ๋น„์ข…์†์„ฑ

Spring Data JPA

  • Spring Module
  • JPA๋ฅผ ์ถ”์ƒํ™”ํ•œ Repository ์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต
  • ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ ๋งŒ์œผ๋กœ๋„ Spring์—์„œ ์ œ๊ณตํ•˜๋Š” CRUD ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Spring Data JPA

JPA
Hibernate
JDBC
<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>
# jpa
spring:
  jpa:
    show-sql: true
  h2:
    console:
      enabled: true
datasource:
    url: jdbc:h2:mem:testdb // h2 1.4.200 ์ด์ƒ

→ h2 console bean์ด ๋“ฑ๋ก๋จ์„ ํ™•์ธ

localhost8088/h2-console → spring security์—์„œ ์„ค์ •ํ•œ ์•„์ด๋””, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ

⇒ mem(memory) : ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ธฐ๋™๋˜๋Š” ๋™์•ˆ์—๋งŒ ์œ ์ง€๋˜๋Š” db

  1. spring security ๊ธฐ๋Šฅ ์‚ญ์ œ → pom.xml์—์„œ dependency ์‚ญ์ œ ๋ฐ SpringConfig.class ์‚ญ์ œ
  2. ์‚ญ์ œ ์•ˆ ํ•˜๊ธฐ

/resource/data.sql์„ ๋งŒ๋“ค์–ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

insert into user values(1, sysdate(), 'User1', 'test1111', '701010-1111111');
insert into user values(2, sysdate(), 'User2', 'test2222', '801010-1111111');
insert into user values(3, sysdate(), 'User3', 'test3333', '901010-1111111');

๊ธฐ๋ณธ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด error๊ฐ€ ๋‚œ๋‹ค!

์Šคํ”„๋ง๋ถ€ํŠธ 2.5๋ฒ„์ „๋ถ€ํ„ฐ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ์™€ .sql ๊ฐ„์˜ ์ˆœ๋ฒˆ์— ์˜ํ•œ ์—๋Ÿฌ์ธ๋“ฏํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„์ „์ด์˜ฌ๋ผ๊ฐ€๋ฉด์„œ .sqlํŒŒ์ผ์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์กŒ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ์‹œ๋ฉด๋ฉ๋‹ˆ๋‹ค.

defer-datasource-initialization: true

jpa:
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: create
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:testdb

์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋“ค์–ด๊ฐ„ ๋ชจ์Šต

Entity ์„ค์ •

@Repository
public interfaceUserRepositoryextendsJpaRepository<User, Integer> {//์–ด๋– ํ•œ Entity๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ธ๊ฐ€,ํ•ด๋‹น entity์˜ ๊ธฐ๋ณธ ํ‚ค ํƒ€์ž…
}
@GetMapping("/users/{id}")
	public EntityModel<User> retrieveUser(@PathVariable int id){
		Optional<User> user = userRepository.findById(id);
		if (!user.isPresent())
			throw new UserNotFoundException(String.format("ID[%s] not found", id));

		// HATEOAS ์‚ฌ์šฉ
		EntityModel<User> entityModel = EntityModel.of(user.get());
		WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retreiveAllUsers());
		entityModel.add(linkTo.withRel("all-users"));

		return entityModel;
	}

H2 Console ์‚ฌ์šฉ์„ ์œ„ํ•œ SecurityConfig ํŒŒ์ผ ์ˆ˜์ •

@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/h2-console/**").permitAll();
		http.csrf().disable();
		http.headers().frameOptions().disable();
	}

JPA Service๋ฅผ ์œ„ํ•œ GET/POST/DELETE ๋ฉ”์†Œ๋“œ์ถ”๊ฐ€

Post Entity ์ถ”๊ฐ€์™€ User Entity์™€์˜ ๊ด€๊ณ„ ์„ค์ •

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {

	@Id
	@GeneratedValue
	private Integer id;

	private String description;

	// User : Post -> 1 : (0~N)
	// Main : Sub -> Parent : Child
	@ManyToOne(fetch = FetchType.LAZY)
	// ์ง€์—ฐ ๋กœ๋”ฉ : ์‚ฌ์šฉ์ž ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ๋ฅผ ํ•  ๋•Œ POST ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋กœ๋”ฉ๋˜๋Š” ๊ฒƒ x
	// post entity๊ฐ€ ์กฐํšŒ๋  ๋•Œ user entity๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒƒ!
	@JsonIgnore
	private User user;

}
@Data
@AllArgsConstructor
@NoArgsConstructor // ๋””ํดํŠธ ์ƒ์„ฑ์ž ์ƒ์„ฑ
@ApiModel(description = "์‚ฌ์šฉ์ž ์ƒ์„ธ ์ •๋ณด๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ ๊ฐ์ฒด")
@Entity
public class User {

	@Id
	@GeneratedValue
	private Integer id;

	@Size(min=2, message = "Name์€ 2๊ธ€์ž ์ด์ƒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String name;

	@Past // ๊ณผ๊ฑฐ ๋‚ ์งœ๋งŒ ๊ฐ€๋Šฅํ•œ ์ œ์•ฝ ์กฐ๊ฑด
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ๋“ฑ๋ก์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private Date joinDate;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String password;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ์ฃผ๋ฏผ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String ssn; // ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ

	@OneToMany(mappedBy = "user")
	private List<Post> posts;
}jpa:
    hibernate:
      ddl-auto: create-drop
      show-sql: true
      generate-ddl: true
      datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:testdb
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console

JPA ๊ฐœ์š”

JPA

  • Java Persistence API
  • ์ž๋ฐ” ORM ๊ธฐ์ˆ ์— ๋Œ€ํ•œ API ํ‘œ์ค€ ๋ช…์„ธ(Object Relationship Mapping)
  • ์ž๋ฐ” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • → ๋ฉ”์†Œ๋“œ ์„ ์–ธ๋ฌธ๋งŒ ์กด์žฌ. ์šฐ๋ฆฌ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐœ๋ฐœ์„ ํ•ด์•ผ ํ•œ๋‹ค ⇒ Hibernate
  • EntityManager๋ฅผ ํ†ตํ•ด CRUD ์ฒ˜๋ฆฌ

Hibernate

  • JPA์˜ ๊ตฌํ˜„์ฒด, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ⇒ JPA์˜ EntityManager๋ฅผ ๊ตฌํ˜„
  • ๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘ ํ”„๋ ˆ์ž„์›Œํฌ
  • ์ƒ์‚ฐ์„ฑ, ์œ ์ง€๋ณด์ˆ˜, ๋น„์ข…์†์„ฑ

Spring Data JPA

  • Spring Module
  • JPA๋ฅผ ์ถ”์ƒํ™”ํ•œ Repository ์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต
  • ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ ๋งŒ์œผ๋กœ๋„ Spring์—์„œ ์ œ๊ณตํ•˜๋Š” CRUD ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Spring Data JPA

JPA
Hibernate
JDBC
<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>
# jpa
spring:
  jpa:
    show-sql: true
  h2:
    console:
      enabled: true
datasource:
    url: jdbc:h2:mem:testdb // h2 1.4.200 ์ด์ƒ

→ h2 console bean์ด ๋“ฑ๋ก๋จ์„ ํ™•์ธ

localhost8088/h2-console → spring security์—์„œ ์„ค์ •ํ•œ ์•„์ด๋””, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ

⇒ mem(memory) : ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ธฐ๋™๋˜๋Š” ๋™์•ˆ์—๋งŒ ์œ ์ง€๋˜๋Š” db

  1. spring security ๊ธฐ๋Šฅ ์‚ญ์ œ → pom.xml์—์„œ dependency ์‚ญ์ œ ๋ฐ SpringConfig.class ์‚ญ์ œ
  2. ์‚ญ์ œ ์•ˆ ํ•˜๊ธฐ

/resource/data.sql์„ ๋งŒ๋“ค์–ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

insert into user values(1, sysdate(), 'User1', 'test1111', '701010-1111111');
insert into user values(2, sysdate(), 'User2', 'test2222', '801010-1111111');
insert into user values(3, sysdate(), 'User3', 'test3333', '901010-1111111');

๊ธฐ๋ณธ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด error๊ฐ€ ๋‚œ๋‹ค!

์Šคํ”„๋ง๋ถ€ํŠธ 2.5๋ฒ„์ „๋ถ€ํ„ฐ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ์™€ .sql ๊ฐ„์˜ ์ˆœ๋ฒˆ์— ์˜ํ•œ ์—๋Ÿฌ์ธ๋“ฏํ•ฉ๋‹ˆ๋‹ค. ๋ฒ„์ „์ด์˜ฌ๋ผ๊ฐ€๋ฉด์„œ .sqlํŒŒ์ผ์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์กŒ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ์‹œ๋ฉด๋ฉ๋‹ˆ๋‹ค.

defer-datasource-initialization: true

jpa:
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: create
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:testdb

์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋“ค์–ด๊ฐ„ ๋ชจ์Šต

Entity ์„ค์ •

@Repository
public interfaceUserRepositoryextendsJpaRepository<User, Integer> {//์–ด๋– ํ•œ Entity๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ธ๊ฐ€,ํ•ด๋‹น entity์˜ ๊ธฐ๋ณธ ํ‚ค ํƒ€์ž…
}
@GetMapping("/users/{id}")
	public EntityModel<User> retrieveUser(@PathVariable int id){
		Optional<User> user = userRepository.findById(id);
		if (!user.isPresent())
			throw new UserNotFoundException(String.format("ID[%s] not found", id));

		// HATEOAS ์‚ฌ์šฉ
		EntityModel<User> entityModel = EntityModel.of(user.get());
		WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retreiveAllUsers());
		entityModel.add(linkTo.withRel("all-users"));

		return entityModel;
	}

H2 Console ์‚ฌ์šฉ์„ ์œ„ํ•œ SecurityConfig ํŒŒ์ผ ์ˆ˜์ •

@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/h2-console/**").permitAll();
		http.csrf().disable();
		http.headers().frameOptions().disable();
	}

JPA Service๋ฅผ ์œ„ํ•œ GET/POST/DELETE ๋ฉ”์†Œ๋“œ์ถ”๊ฐ€

Post Entity ์ถ”๊ฐ€์™€ User Entity์™€์˜ ๊ด€๊ณ„ ์„ค์ •

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {

	@Id
	@GeneratedValue
	private Integer id;

	private String description;

	// User : Post -> 1 : (0~N)
	// Main : Sub -> Parent : Child
	@ManyToOne(fetch = FetchType.LAZY)
	// ์ง€์—ฐ ๋กœ๋”ฉ : ์‚ฌ์šฉ์ž ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ๋ฅผ ํ•  ๋•Œ POST ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋กœ๋”ฉ๋˜๋Š” ๊ฒƒ x
	// post entity๊ฐ€ ์กฐํšŒ๋  ๋•Œ user entity๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ฒƒ!
	@JsonIgnore
	private User user;

}
@Data
@AllArgsConstructor
@NoArgsConstructor // ๋””ํดํŠธ ์ƒ์„ฑ์ž ์ƒ์„ฑ
@ApiModel(description = "์‚ฌ์šฉ์ž ์ƒ์„ธ ์ •๋ณด๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ ๊ฐ์ฒด")
@Entity
public class User {

	@Id
	@GeneratedValue
	private Integer id;

	@Size(min=2, message = "Name์€ 2๊ธ€์ž ์ด์ƒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String name;

	@Past // ๊ณผ๊ฑฐ ๋‚ ์งœ๋งŒ ๊ฐ€๋Šฅํ•œ ์ œ์•ฝ ์กฐ๊ฑด
	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ๋“ฑ๋ก์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private Date joinDate;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String password;

	@ApiModelProperty(notes = "์‚ฌ์šฉ์ž์˜ ์ฃผ๋ฏผ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")
	private String ssn; // ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ

	@OneToMany(mappedBy = "user")
	private List<Post> posts;
}jpa:
    hibernate:
      ddl-auto: create-drop
      show-sql: true
      generate-ddl: true
      datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:testdb
    defer-datasource-initialization: true
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
        path: /h2-console

๋Œ“๊ธ€