src - main - resources - application.properties 파일에서 Rename (shift + F6)으로 들어가서 application.yml로 이름 변경
JPA, DB 설정 추가하기
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/[schema이름]
username: [username]
password: [비밀번호]
#jpa
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true #sql format 적용
환경변수로 Envrionment Variable을 통해 진짜 url, password를 넘겨줍니다.
SPRING_DATASOURCE_URL=jdbc:mysql://[ec2주소]:3306
SPRING_DATASOURCE_PASSWORD=[비밀번호]
root 디렉토리에 entity 패키지에 생성 - User 클래스 생성
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String userName;
@Column(nullable = false)
private String password;
public User() {
}
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public Long getId() {
return id;
}
public String getUserName() {
return userName;
}
public String getPassword() {
return password;
}
}
원시 타입(long)은 기본값이 0으로, 실제 값과 초기값이 없을 때와 판별하기 어렵습니다.Wrapper 클래스는 값이 없을 경우 null로 초기화되기 때문에 실제 값이 없는지 알 수 있습니다.
시간이 지남에 따라 데이터가 쌓이면 id값이 증가할 경우를 대비할 수 있습니다.
@Entity
@Table
@Id
@GeneratedValue
@Column
@OneToMany / @ManyToOne
User entity에서 get 메소드, 생성자들을 삭제하고, Lombok 어노테이션을 적용합니다.
@Builder 어노테이션을 사용하기 위해서는 전체 필드를 포함하는 생성자가 필요하므로, @AllArgsConstructor도 추가해줍니다.
@Entity
@NoArgsConstructor
@Getter
@Builder
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String userName;
@Column(nullable = false)
private String password;
}
Builder 패턴은 객체 생성을 유연하게 하기 위한 디자인 패턴 중 하나입니다. 일반적으로 많은 매개변수를 가진 객체를 생성할 때, 가독성을 높이고 코드 작성을 간편하게 하기 위해 사용됩니다.
Builder 패턴은 다음과 같은 특징을 가지고 있습니다:
@Builder 어노테이션은 Lombok에서 제공하는 어노테이션 중 하나로, Builder 패턴을 자동으로 생성해주는 기능을 제공합니다. @Builder 어노테이션을 클래스에 적용하면 해당 클래스에 대한 Builder 클래스가 자동으로 생성되고, 필드 값의 설정을 간편하게 할 수 있습니다.
intellij의 DB 또는 workbench를 통해서 entity의 테이블이 설정대로 만들어졌는지 확인
리포지토리를 생성하기 위해서는 접근하려는 테이블과 매핑되는 엔티티에 대한 인터페이스를 생성하고, JpaRepository를 상속받으면 됩니다.
JpaRepository를 상속받을 때는 대상 엔티티(User)와 해당 엔티티의 기본값 타입 (Long)을 지정해야 합니다.
생성된 리포지토리는 JpaRepository를 상속받으면서 별도의 메서드 구현 없이도 많은 기능을 제공합니다. 일반적으로 CRUD에서 따로 생성해서 사용하는 메서드는 Read에 해당하는 SELECT 쿼리밖에 없습니다.
import com.springboot.jpa.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
UserRepositoryTest 생성하기
UserRepositoy에서 cmd + N
- Test..
탭 - OK
클릭
src
- test
- root 디렉토리
- repository 패키지
안에 테스트 클래스에 어노테이션 추가
import com.springboot.jpa.entity.User;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ActiveProfiles;
@DataJpaTest
@ActiveProfiles("test")
@Rollback(value = false)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
}
spring:
jpa:
show-sql: true
hibernate:
ddl-auto: create
defer-datasource-initialization: true
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/[스키마 이름]
username: root
password: password!
아래 테스트 실행 후 DB에 데이터 생성 확인
@Test
@DisplayName("유저 등록")
void 유저등록() {
User user = userRepository.save(User.builder().userName("이름").password("비밀번호").build());
}
@Test
@DisplayName("유저 수정")
void 유저수정() {
//유저 등록
User saved = userRepository.save(User.builder().userName("이름").password("비밀번호").build());
assertEquals("이름", saved.getUserName());
//유저 이름 수정
User updated = userRepository.save(User.builder().id(saved.getId()).userName("수정된이름").password(saved.getPassword()).build());
assertEquals("수정된이름", updated.getUserName());
}
@Test
@DisplayName("유저 삭제")
void 유저삭제() {
//유저 등록
User saved = userRepository.save(User.builder().userName("이름").password("비밀번호").build());
assertEquals("이름", saved.getUserName());
//유저 삭제
userRepository.deleteById(saved.getId());
}
@Test
@DisplayName("유저 아이디로 찾기")
void 유저아이디로검색() {
//유저 등록
User saved = userRepository.save(User.builder().userName("이름").password("비밀번호").build());
assertEquals("이름", saved.getUserName());
//유저 아이디로 검색
Optional<User> optionalUser = userRepository.findById(saved.getId());
assertEquals("이름", optionalUser.get().getUserName());
//유저 삭제 후 검색
userRepository.deleteById(saved.getId());
Optional<User> deletedUser = userRepository.findById(saved.getId());
assertTrue(deletedUser.isEmpty());
}
@Test
@DisplayName("전체 유저 검색")
void 유저전체검색() {
//유저 등록
User saved1 = userRepository.save(User.builder().userName("이름1").password("비밀번호").build());
User saved2 = userRepository.save(User.builder().userName("이름2").password("비밀번호").build());
User saved3 = userRepository.save(User.builder().userName("이름3").password("비밀번호").build());
User saved4 = userRepository.save(User.builder().userName("이름4").password("비밀번호").build());
User saved5 = userRepository.save(User.builder().userName("이름5").password("비밀번호").build());
//유저 아이디로 검색
List<User> users = userRepository.findAll();
assertEquals(5, users.size());
//유저 삭제 후 검색
userRepository.deleteById(saved1.getId());
userRepository.deleteById(saved2.getId());
List<User> usersAfter = userRepository.findAll();
assertEquals(3, usersAfter.size());
}
@NoRepositoryBean
public interface JpaRepository<T, ID> extends ListCrudRepository<T, ID>, ListPagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
void flush();
<S extends T> S saveAndFlush(S entity);ㅍ
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
@Deprecated
default void deleteInBatch(Iterable<T> entities) {
deleteAllInBatch(entities);
}
void deleteAllInBatch(Iterable<T> entities);
void deleteAllByIdInBatch(Iterable<ID> ids);
void deleteAllInBatch();
@Deprecated
T getOne(ID id);
@Deprecated
T getById(ID id);
T getReferenceById(ID id);
<S extends T> List<S> findAll(Example<S> example);
@Override
<S extends T> List<S> findAll(Example<S> example, Sort sort);
JpaRepository 인터페이스는 일반적인 CRUD(Creating, Reading, Updating, Deleting) 작업을 수행하기 위한 메서드를 자동으로 생성해주는 기능을 제공합니다. JpaRepository를 상속한 인터페이스를 정의하면, 해당 인터페이스의 메서드들은 자동으로 JPA 쿼리로 변환되어 데이터베이스에 접근할 수 있습니다.