์ค๋์ ์ฃผ์์ฌํญ (6/16, ๊ธ์์ผ)
- JPA ํ์ต
- ๊ฐ์ธ๊ณผ์ ๋ง๋ฌด๋ฆฌ
JPA๋ฅผ ์ ์ฉํ๋ ๊ฒ๊น์ง๊ฐ ๊ณผ์ ์ธ ๊ฒ ๊ฐ์์... ์ด์ ์ ๊ทธ์น์ง ์๊ณ ์กฐ๊ธ ๋ ์ด์ ๋ถ์ฌ๋ณด์๋ค.
JPA๋ฅผ ์ถ๊ฐํ๋ฉด์ JDBC๋ ์ฌ์ฉํ ์ผ์ด ์์ด์ง๊ธฐ ๋๋ฌธ์, JPA ์ค์ ์ถ๊ฐ์ ํจ๊ป JDBC ์ค์ ์ ์ง์์ฃผ๊ธฐ๋ก ํ๋ค.
dependencies {
/* ์ค๋ต */
// JPA ์ค์
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}
spring.jpa.database=mysql
spring.datasource.username=root
spring.datasource.password=12345678
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.hibernate.ddl-auto
๋ฅผ create
๋ก ์ค์ ํด์ฃผ๋ฉด, ๊ธฐ์กด ์์ฑ๋์ด์๋ ํ
์ด๋ธ์ ๋ฌด์ํ๊ณ ์๋ก์ด ํ
์ด๋ธ์ ์์ฑํด์ค๋ค.
ํ
์ด๋ธ ์ ๋ณด๋ฅผ ์ฝ๋๊ฐ ์ธ์ํ๊ณ ๋ฃ์ด์ค ์ ์๋๋ก @์ ๋
ธํ
์ด์
์ ํ์ฉํ์ฌ ์ ๋ณด๋ฅผ ๋ช
์ํด์ค๋ค.
๊ธฐ์กด์ ์ฌ์ฉํ๋ create table
๋ช
๋ น์ด์ ๋ฐ๋ entity
๋ฅผ ํจ๊ป ์ดํด๋ณด์.
create table post (
id int not null auto_increment,
createdAt DATETIME not null,
modifiedAt DATETIME not null,
title varchar(255) not null,
content varchar(500) not null,
author varchar(255) not null,
password varchar(255) not null,
primary key (id)
);
@Entity // JPA๊ฐ ๊ด๋ฆฌํ ์ ์๋ Entity ํด๋์ค ์ง์
@Getter
@Setter
@Table(name = "post") // ๋งคํํ ํ
์ด๋ธ์ ์ด๋ฆ์ ์ง์
@NoArgsConstructor
public class Blog extends Timestamped {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id; // id
@Column(name = "title", nullable = false)
private String title; // ์ ๋ชฉ
@Column(name = "content", nullable = false)
private String content; // ๋ด์ฉ
@Column(name = "author", nullable = false)
private String author; // ์์ฑ์
@Column(name = "password", nullable = false, length = 12)
private String password; // ๋น๋ฐ๋ฒํธ
/* ์์ฑ์์ ๋ฉ์๋๋ ๋์ผํ ํํ์ด๋ค */
}
JPA์ ํ์ฉํ๋ฉด @Column
๋ฑ๊ณผ ๊ฐ์ ์ ๋
ธํ
์ด์
์ ์ฌ์ฉํด, create table
๋ช
๋ น๋ฌธ๊ณผ ๋์ผํ ํจ๊ณผ๋ฅผ ๋ผ ์ ์๋ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์๋ฅผ ๋ค์ด์
title varchar(255) not null,
์,
@Column(name = "title", nullable = false)
private String title; // ์ ๋ชฉ
์ด์ ์ด๋ ๊ฒ ์ฌ์ฉํจ์ผ๋ก์จ Java-Spring ์ฝ๋๊ฐ ์ธ์ํ ์ ์๊ฒ ๋์๋ค๋ ๊ฒ์ด๋ค.
์๊ฐ ํ์
์ ๋ค์ varchar
์์ DATETIME
์ผ๋ก ๋ณ๊ฒฝํด์ฃผ์๋ค. DATETIME
์ผ๋ก ์ ์ฅ๋์ด๋, ๋ฐ๋ฆฌ์ด๊น์ง ์กฐํํ ์ ์๋ค๊ณ ํ๋ค.
๋ณ๊ฒฝ์ ๋ฐ๋ผ ์๊ฐ ์ ๋ณด๋ฅผ ์ ์ฅํ entity
๋ฅผ ์๋กญ๊ฒ ์์ฑํ๊ฒ ๋์๋ค. ์ด Timestamped
entity๋ ์ถ์ ํด๋์ค
๋ก, Blog
๊ฐ ์์ ๋ฐ์ ์ฌ์ฉํ๊ฒ ๋๋ค.
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Timestamped {
@CreatedDate
@Column(updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime createdAt;
@LastModifiedDate
@Column
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime modifiedAt;
}
BlogRepository
๋ JpaRepository
๋ฅผ ์์ํ๊ฒ ๋จ์ผ๋ก์จ, ๋ฐ๋ก ๊ตฌํ๋ถ๋ฅผ ์์ฑํ ํ์๊ฐ ์์ด์ก๋ค.
public interface BlogRepository extends JpaRepository<Blog, Integer> {
}
์ด๋ฌํ ์ํ๋ง์ผ๋ก๋ JpaRepository
๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํด์ฃผ๋ ๊ธฐ๋ฅ์ ๋๋ถ๋ถ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค. ํ์ง๋ง JpaRepository
๊ธฐ๋ณธ ์ ๊ณต ๊ธฐ๋ฅ ์ธ์, ๋ค๋ฅธ ์ ์ฌํ ๊ธฐ๋ฅ๋ค์ด ํ์ํด์ง๋ค๋ฉด, ์๋์ ๊ฐ์ด ์ ์ธํจ์ผ๋ก์จ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
public interface BlogRepository extends JpaRepository<Blog, Integer> {
// ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ - CreatedAt (์์ฑ ์๊ฐ)์ ๊ธฐ์ค์ผ๋ก
List<Blog> findAllByOrderByCreatedAtDesc();
// Id์ Password๋ฅผ ์ฌ์ฉํด Blog๋ฅผ ์ฐพ์์ ๋ฐํ
Blog findByIdAndPassword(Integer id, String password);
}
๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ findById()
์ธ์, ๋น๋ฐ๋ฒํธ(password)๋ ํจ๊ป ์กฐํํ๊ณ ์ถ์ด์, findByIdAndPassword()
๋ผ๋ ๋ฉ์๋๋ฅผ ํจ๊ป ๋ง๋ค์ด์ ์ ์ธํด์ฃผ์๋ค.
Repository์์ ๊ตฌํํ๋ค๋ฉด, ํธ์ถ์ ๋ง์ฐฌ๊ฐ์ง๋ก Service๊ฐ ํ๋ค.
findByIdAndPassword()
๋ฅผ ํ์ฉํด id์ ๋น๋ฐ๋ฒํธ๋ฅผ ํจ๊ป ์ฒดํฌํ ์ ์๊ฒ ๋์๋ค.
@Transactional
public BlogResponseDto updateBlogPost(Integer id, BlogRequestDto requestDto) {
// 1. ํด๋น ๊ฒ์๊ธ์ด DB์ ์กด์ฌํ๋์ง ํ์ธ
Blog blog = blogRepository.findByIdAndPassword(id, requestDto.getPassword());
if(blog != null) {
// 2. ์กด์ฌํ๋ฉด blog ์์
blog.update(requestDto); // DB ์ ์ฅ
BlogResponseDto blogResponseDto = new BlogResponseDto(blog);
return blogResponseDto;
} else {
throw new IllegalArgumentException("๋น๋ฐ๋ฒํธ๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค.");
}
}
ํ
์ด๋ธ์ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ์ํ๊ธฐ ์ํด์๋ @Transactional
์ ๋
ธํ
์ด์
์ด ํ์ํ๋ค.
createdAt
์ ๊ธฐ๋ฐ์ผ๋ก ํ ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ์ ์๋์ ๊ฐ์ด ๋ณ๊ฒฝ๋์๋ค.
// BlogService.java
public List<BlogResponseDto> getBlogPosts() {
// DB ์กฐํ
return blogRepository.findAllByOrderByCreatedAtDesc().stream().map(BlogResponseDto::new).toList();
}
/blog/posts
/blog/post/{id}
blog/post/{id}
/blog/post/{id}
/blog/post
blog/post/{id}