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
- spring security ๊ธฐ๋ฅ ์ญ์ → pom.xml์์ dependency ์ญ์ ๋ฐ SpringConfig.class ์ญ์
- ์ญ์ ์ ํ๊ธฐ
/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
- spring security ๊ธฐ๋ฅ ์ญ์ → pom.xml์์ dependency ์ญ์ ๋ฐ SpringConfig.class ์ญ์
- ์ญ์ ์ ํ๊ธฐ
/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
- spring security ๊ธฐ๋ฅ ์ญ์ → pom.xml์์ dependency ์ญ์ ๋ฐ SpringConfig.class ์ญ์
- ์ญ์ ์ ํ๊ธฐ
/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
- spring security ๊ธฐ๋ฅ ์ญ์ → pom.xml์์ dependency ์ญ์ ๋ฐ SpringConfig.class ์ญ์
- ์ญ์ ์ ํ๊ธฐ
/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
- spring security ๊ธฐ๋ฅ ์ญ์ → pom.xml์์ dependency ์ญ์ ๋ฐ SpringConfig.class ์ญ์
- ์ญ์ ์ ํ๊ธฐ
/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
'๐ฟ Spring > โ RESTful Web Service' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
6. RESTful API ์ค๊ณ ๊ฐ์ด๋ (0) | 2023.06.20 |
---|---|
4. Spring Boot API ์ฌ์ฉ (0) | 2023.06.20 |
3. RESTful Service ๊ธฐ๋ฅ ํ์ฅ (0) | 2023.06.20 |
2. User Service API ๊ตฌํ (0) | 2023.06.20 |
1. Spring Boot๋ก ๊ฐ๋ฐํ๋ RESTful Service (0) | 2023.06.20 |
๋๊ธ