반응형
@OneToMany(fetch = FetchType.EAGER): 1대N 연관관계를 즉시 로딩할 수 있도록 선언한다.
@JoinColumn(name = "user_id", insertable = false, updatable = false): 선언된 테이블에서는 선언한 컬럼의 해당하는 테이블에 데이터가 수정되거나 생성되지 않도록 선언한다.
@Column(name = "user_id"): 컬럼명을 연관관계에 있는 테이블에 컬럼과 맞춰준다.
예제 코드
User 클래스
package com.example.bookmanager.domain;
import com.example.bookmanager.domain.listener.UserEntityListener;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Data
@Builder
@Entity
//@EntityListeners(value = {MyEntityListener.class, UserEntityListener.class})
//공통 Entity 사용
@EntityListeners(value = {AuditingEntityListener.class, UserEntityListener.class})
//@Table(name = "user", indexes = {@Index(columnList = "name")}, uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User extends BaseEntity{
@Id
// 테이블마다 ID값이 증가하도록 설정
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NonNull
private String name;
@NonNull
private String email;
// update 할 경우 값을 제외하도록 설정
@Column(updatable = false)
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
@Enumerated(value = EnumType.STRING)
private Gender gender;
// @Transient
// private String testData;
public User(String name, String email, LocalDateTime creDate, LocalDateTime upDate) {
this.name = name;
this.email = email;
this.createdAt = creDate;
this.updatedAt = upDate;
}
//@OneToMany(fetch = FetchType.EAGER)
//private List<Address> address;
// Entity Listener 이벤트 정의 및 동작 시점 확인
@PrePersist
public void prePersist(){
System.out.println(">>> prePersist");
// 사용자가 입력을 안해주어도 자동으로 현재 날짜를 입력하도록 설정
this.createdAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
}
@PostPersist
public void postPersist(){
System.out.println(">>> postPersist");
}
@PreUpdate
public void preUpdate(){
System.out.println(">>> preUpdate");
// Update를 진행할 때 자동으로 update를 진행한 날짜를 입력하도록 설정
this.updatedAt = LocalDateTime.now();
}
@PostUpdate
public void postUpdate(){
System.out.println(">>> postUpdate");
}
@PreRemove
public void preRemove(){
System.out.println(">>> preRemove");
}
@PostRemove
public void postRemove(){
System.out.println(">>> postRemove");
}
@PostLoad
public void postLoad(){
System.out.println(">>> postLoad");
}
// 1대N 관계
// null 예외처리를 방지하기 위해서 arrayList 생성자를 선언해준다.
@OneToMany(fetch = FetchType.EAGER)
// UserHistory 테이블에 컬럼과 맞춰준다.
// User 테이블에서는 History 테이블 컬럼에 데이터를 삽입하거나 수정하지 못하도록 한다.
@JoinColumn(name = "user_id", insertable = false, updatable = false)
private List<UserHistory> userHistories = new ArrayList<>();
}
UserHistroy 클래스 예제
package com.example.bookmanager.domain;
import com.example.bookmanager.domain.listener.Auditable;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.time.LocalDateTime;
@Data
// 상속받은 BaseEntity를 사용하기 위해서 ToString, EqualsAndHashCode 재정의
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Entity
@NoArgsConstructor
// 자동으로 생성날짜, 수정날짜를 입력해주기 위해서 선언
//@EntityListeners(value = MyEntityListener.class)
// 공통 클래스 사용
//@EntityListeners(value = AuditingEntityListener.class)
// User객체에 History를 저장할 객체 생성
// BaseEntity를 상속받아 그 안에 있는 설정들을 사용할 수 있다.
public class UserHistory extends BaseEntity{
@Id
// 테이블마다 ID값이 증가하도록 설정
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_id")
private Long userId;
@NonNull
private String name;
@NonNull
private String email;
// update 할 경우 값을 제외하도록 설정
// @Column(updatable = false)
// 자동으로 해당값을 넣어준다.
// @CreatedDate
// private LocalDateTime createdAt;
// 자동으로 해당값을 넣어준다.
// @LastModifiedDate
// private LocalDateTime updatedAt;
}
UserEntityListener 클래스
package com.example.bookmanager.domain.listener;
import com.example.bookmanager.domain.User;
import com.example.bookmanager.domain.UserHistory;
import com.example.bookmanager.repository.UserHistoryRepository;
import com.example.bookmanager.support.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.persistence.PostPersist;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
// Autowired를 사용할 경우 spring bean 등록을 진행해야 하기 때문에 Component 어노테이션을 사용한다.
//@Component
public class UserEntityListener {
// @Autowired
// private UserHistoryRepository userHistoryRepository;
// 업데이트, 생성를 진행할 경우 자동으로 history에 저장되도록 설정
// @PreUpdate
// @PrePersist
// 저장한 이후에 동작하도록 재지정
@PostPersist
@PostUpdate
public void prePersistAndPreUpdate(Object o) {
// UserHistoryRepository의 bean을 가져온다.
UserHistoryRepository userHistoryRepository = BeanUtils.getBean(UserHistoryRepository.class);
User user = (User) o;
UserHistory userHistory = new UserHistory();
userHistory.setUserId(user.getId());
userHistory.setName(user.getName());
userHistory.setEmail(user.getEmail());
userHistoryRepository.save(userHistory);
}
}
UserHistoryRepository 클래스
package com.example.bookmanager.repository;
import com.example.bookmanager.domain.UserHistory;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface UserHistoryRepository extends JpaRepository<UserHistory, Long> {
// userId 값으로 데이터를 찾을수 있도록 선언
List<UserHistory> findByUserId(Long userId);
}
UserRepositoryTest 테스트 코드 추가
// 1 대 N 테스트
@Test
void userRelationTest() {
Dto();
User user = new User();
user.setName("david");
user.setEmail("david@naver.com");
user.setGender(Gender.MALE);
userRepository.save(user);
user.setName("daniel");
userRepository.save(user);
user.setEmail("daniel@naver.com");
userRepository.save(user);
// 자동으로 userHistory 테이블에 저장되는것을 확인할 수 있다.
// userHistoryRepository.findAll().forEach(System.out::println);
// userId 값으로 데이터 확인(특정 이메일의 Id를 가져와서 조회)
List<UserHistory> result = userHistoryRepository.findByUserId(
userRepository.findByEmail("daniel@naver.com").getId());
//result.forEach(System.out::println);
List<UserHistory> result2 = userRepository.findByEmail("daniel@naver.com").getUserHistories();
result2.forEach(System.out::println);
}
콘솔 확인
반응형
'Spring > JPA' 카테고리의 다른 글
N대N 연관관계 설정 2 (중간테이블을 만들어서 사용하는 방법) (0) | 2021.08.29 |
---|---|
N 대 N 연관관계 설정 (0) | 2021.08.29 |
1 대 1 관계 설정하는 방법 (0) | 2021.07.24 |
연관 관계 설정 -1 (0) | 2021.07.24 |
연관관계, ERD (0) | 2021.07.24 |