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 ๊ธฐ๋ฅ ์ฌ์ฉ ๊ฐ๋ฅ
1. dependency ์ถ๊ฐ
<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 ์ด์์์๋ ๋ช
์ํด์ค์ผ ํจ
2. h2 console ๋ก๊ทธ์ธ
localhost8088/h2-console → spring security์์ ์ค์ ํ ์์ด๋, ๋น๋ฐ๋ฒํธ ์ ๋ ฅํ๊ณ ์ง์ .
ํ์ง๋ง ์ด๊ฒ ๊ท์ฐฎ๋ค๋ฉด spring security ๊ธฐ๋ฅ์ ์ญ์ ํด๋ ๋๋ค -> dependency, SpringConfig.class ์ญ์
๊ทธ๋ฆฌ๊ณ ์๋ฒ๋ฅผ ๊ตฌ๋์์ผ๋ณด๋ฉด hibernate์์ ์ฑ๊ณต์ ์ผ๋ก table์ ์์ฑํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
(application.yml์ jpa : show-sql: trueํ ๊ฒฝ์ฐ๋ง ๋ณด์)
3. ์ด๊ธฐ ๋ฐ์ดํฐ ์ฝ์
์์์ฉ์ผ๋ก /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');
hibernate - sql ๋ฒ์ ์๋ฌ
๊ทธ๋ฐ๋ฐ ์๋ฅผ ์คํํ๋ฉด ์๋ฌ๊ฐ ๋๋ค! ์ฐพ์๋ณด๋ Spring Boot 2.5๋ฒ์ ๋ถํฐ hibernate์ sql ๊ฐ์ ์์๊ฐ ๋ฐ๋์ด sql ํ์ผ์ด ๋จผ์ ์คํ๋๋ค๊ณ ํ๋ค. sql์ ์คํํด์ผ ํ๋๋ฐ table์ ์์ผ๋ ๋น์ฐํ ์๋ฌ๊ฐ ๋๋ค......์๋ ์ ์ฐ ๊ฐ์๋ผ ๋ฒ์ ์ค๋ฅ๊ฐ ์ฐธ ๋ง๋ค^^
application.yml ํ์ผ์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
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
4. Entity ์ค์
[interfaceUserRepository]
@Repository
public interfaceUserRepository extends JpaRepository<User, Integer> {
//์ด๋ ํ Entity๋ฅผ ๋ค๋ฃฐ ๊ฒ์ธ๊ฐ,ํด๋น entity์ ๊ธฐ๋ณธ ํค ํ์
}
[Controller]
@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;
}
5. H2 Console ์ฌ์ฉ์ ์ํ SecurityConfig ํ์ผ ์์
๊ธฐ๋ณธ์ ์ผ๋ก spring security๋ ๋ชจ๋ ์์ฒญ์ ๋ชจ๋ ๋ง๋๋ค! ๊ทผ๋ฐ ์ฐ๋ฆฌ๋ h2 console์ ์ ๊ทผํด์ผ ํ๋๊น ํด๋น ์ฝ์์์ ์ค๋ ์์ฒญ์ ์ด์ด๋์.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/h2-console/**").permitAll();
http.csrf().disable();
http.headers().frameOptions().disable();
}
6. Post Entity์ User Entity ์์ฑ ๋ฐ ๊ด๊ณ ์ค์
ํ๋์ ์ ์ ๊ฐ ์ฌ๋ฌ ๊ฐ์ post๋ฅผ ์์ฑํ ์ ์๋๋ก ๋๊ณ ๊ด๋ จ๋ ์ํฐํฐ๋ฅผ ๋ง๋ค์ด์ค๋ค.
@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 {
...
@OneToMany(mappedBy = "user")
private List<Post> posts;
}
๋๊ธ