반응형

📝@Entity, @Id, @GeneratedValue, @Temporal, @Lob

public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // IDENTITY 전략
    // @GeneratedValue(strategy = GenerationType.SEQUENCE) // SEQUENCE 전략
    @Column(name="member_id")
    private Long id;

    private String name;
    private int age;
    private String address; // 필드만 추가해주면 끝

    // @Enumerated(EnumType.ORDINAL) // enum 타입 매핑 [숫자] (금지)
    @Enumerated(EnumType.STRING) // enum 타입 매핑 [문자] (사용 OK)
    private CategoryEnum name;

    // 날짜 타입 매핑 [아래 LocalDateTime을 쓰면 알아서 YYYYMMDDHHMMSS 설정]
    @Temporal(TemporalType.DATE) 
    private Date date;
    
    private LocalDateTime createDate
    
    @Lob // BLOB, CLOB 매핑
    private String description;
}

 

  • @Entity 
    • JPA에서 영속성 컨텍스트가 관리할 테이블이라는 의미이다.
  • @Id
    • 해당 필드를 PK로 지정하겠다는 의미이다.
  • @GeneratedValue
    • PK AutoIncrement설정이다. IDENTITY로 설정할지 SEQUENCE로 지정할지 정할 수 있다.
  • @Temporal
    • 날짜 필드라는 걸 알리는 의미이다.
  • @Lob
    • BLOB, CLOB타입이라는 걸 알리는 의미이다.

 

📝@JoinColumn, @ManyToOne, @OneToMany, @OneToOne, @ManyToMany

@Entity
public class Member {

    @Id // PK로 설정할 컬럼
    @GeneratedValue
    private long id;

    @Column(nullable = false, length = 10)
    private String name;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID") // Team 테이블[클래스]에 연결할 필드명을 알려주세요 
                                  // (JoinColumn은 FK가 있는 테이블에 들어간다)
    private Team team;

}

@Entity
public class Team {

    @Id @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    private String name;

}
  • @JoinColumn
    • 연결할 테이블에 필드를 지정한다
  • @ManyToOne
    • 다대일 관계로 연결하겠다는 의미
  • @OneToMany
    • 일대다 관계로 연결하겠다는 의미
  • @OneToOne
    • 일대일 관계로 연결하겠다는 의미
  • @ManyToMany (사용 X)
    • 다대다 관계로 연결하겠다는 의미 (다대다 관계는 무조건 다대일로 풀어내야한다)

 

 

📝@Inheritance, @DiscriminatorColumn, @DiscriminatorValue

@Inheritance(strategy = InheritanceType.JOINED) // 조인 전략
@DiscriminatorColumn 
@Entity
public class Item {

    @Id
    @GeneratedValue
    private long id;

    private String name;
    private int price;
}

@Entity
// @DiscriminatorValue("this is movie")
public class Movie extends Item{

    private String director;
    private String actor;

}

public class Main {
    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        tx.begin();

        try{

            Movie movie = new Movie();
            movie.setName("바람과 함께 사라지다");
            movie.setPrice(10000);
            movie.setActor("이민호");
            movie.setDirector("봉준호");

            em.persist(movie);

            tx.commit();

        }catch (Exception e){
            e.printStackTrace();
        }finally{
            emf.close();
            em.close();
        }
    }
}

 

@Inheritance

관계형 데이터베이스에 상속관계라는 걸 JPA에서 표현했다

 

 

 

 

@DiscriminatorColumn

해당 어노테이션을 사용 안 하면 DTYPE이 따로 안 보이는데 이걸 명시적으로 표현해주는 어노테이션 어느 자식이 UPSERT 되어서 그런지 잘 모르니 해당 어노테이션을 사용하는게 좋다

 

 

 

 

@DiscriminatorValue

해당 어노테이션을 사용하면 DTYPE에 들어갈 걸 명시적으로 지정할 수 있다.

 

 

 

 

 

 

 

 

📝@MappedSuperclass

@MappedSuperclass
public abstract class BaseEntity {

    @Column(name = "create_date") // 부모 클래스에서 컨트롤 가능
    private LocalDateTime localDateTime;

    private LocalDateTime modi_date;
}

@Entity
public class Book extends BaseEntity{

    @Id
    @GeneratedValue
    private long id;

    private String name;
    private String author;
    private String ISBN;

}

Inheritance와 차이가 있는 점은 Inheritance은 부모 자식 테이블 따로따로 들어가게 되는데 MappedSuperclass의 경우 필드만 공유하고 하나의 테이블로 만들어진다.

 

 

📝@NamedQuery, @Query

@Entity
@NamedQuery(
    name="Member.findByUsername", // Key
    query="select m from Member m where m.username = :username" // Value
)
public class Member {

    @Id @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String username;
    private int age;

}

public interface MemberRepository extends JpaRepository<Member, Long> {

    /** ----- 방법1 (@Query) ----- **/
    @Query(name ="Member.findByUsername")
    List<Member> findByUsername(@Param("username") String username);
    
    /** ----- 기본 예제 ----- **/
    @Query("select m from Member m where m.username = :username and m.age = :age")
    List<Member> findUser(@Param("username") String username, @Param("age") int age);

}

조건절 조회하는 임의의 쿼리가 필요할 때 Entity에 @NamedQuery를 이용해 JpaRepository에서 {키:값} 형태로 찾아 사용이 가능하다

이 방법보단 JpaRepository에서 바로 @Query를 이용해 바로 작성하는 걸 더 많이 사용한다

 

📝@Modifying

public interface MemberRepository extends JpaRepository<Member, Long> {

    @Modifying(clearAutomatically = true)
    @Query("update Member m set m.age = m.age + 1 where m.age >= :age")
    int bulkAgePlus(@Param("age") int age);
 
}

Update한 후에 Update 항목을 조회하는 경우가 있을 때 영속성 컨텍스트 캐시를 날리고 데이터 조회하기 때문에 디비에서 조회하게 되고  데이터의 정합성을 맞춘다

 

📝@EntityGraph

public interface MemberRepository extends JpaRepository<Member, Long> {

    @EntityGraph(attributePaths = {"team"})
    @Query("select m from Member m")
    // 위에 코드는 EntityGraph + Query로 아래와 같은 코드이다. (team Fetch Join)

    // @Query("select m from Member m left join fetch m.team")
    List<Member> findMemberEntityGraph();
}

패치조인을 더 쉽게할 수 있도록 스프링 데이터 JPA에서 제공해준다.

 

엔터티 라이프 사이클 컨트롤 어노테이션 (@PrePersist, @PreUpdate, @PreRemove, @PostPersist, @PostUpdate, @PostRemove, @PostLoad)

@PrePersist : 새로운 엔티티에 대해 persist가 호출되기 전
@PreUpdate : 엔티티 업데이트 작업 전
@PreRemove : 엔티티가 제거되기 전
@PostPersist : 새로운 엔티티에 대해 persist가 호출된 후
@PostUpdate : 엔티티가 업데이트된 후
@PostRemove : 엔티티가 삭제된 후
@PostLoad : Select조회가 일어난 직후에 실행
반응형