2016년 3월 23일 수요일

[JPA연관관계매핑]복합키와 식별관계,비식별관례,엔티티매핑
 
엔티티 매핑(Entity Mapping) – 연관관계
 
n  두 엔티티가 연관을 맺는 연관관계에는 방향성(direction), 다양(중)성(multiplicity), 주체(owner)라는 개념이 존재한다.
ü  Direction : 두 객체가 관계를 맺을 때 한쪽에서만 참조하는 경우 단 방향이라 하고 양쪽 객체가 서로 참조하는 경우를 양방향 연관관계라고 한다.
ü  Multiplicity : 하나의 객체가 참조하는 객체가 한 개, 한 개 이상 등 다양성이 있는데 1:1, 1:N, M:N관계가 있다.
ü  Owner : 연관관계에서의 주인이 되는 객체
 
2-4-1. 복합키와 비식별 관계
 
n  외래키가 기본키에 포함되는지 여부에 따라 식별관계, 비식별 관계로 구별할 수 있다.
n  아래의 경우 부모테이블의 키가 자식테이블에 참조되는데 비 식별관계이다. 부모테이블의 PK가 자식테이블에 외래키(FK)로 참조될 때 기본키(PK)로 내려가는 것이 아니라 일반 칼럼으로 참조되는 것이다.
 

 
:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
@Entity
public class Parent {
   @EmbeddedId
   protected ParentKey pkey;
          
   @Embeddedable
   public static class ParentKey implements Serializable
   {                
      @Column
      private String id1;
      @Column
      private String id2;            
      //getter, setter, equals, hashCode는 구현해야 한다.
   }
}
 
@Entity
public class Child {
   @Id
   private String id;
          
   @ManyToOne
   @JoinColumns({     
       @JoinColumn(name="parent_id1",referencedColumnName="id1"),
       @JoinColumn(name="parent_id2", referencedColumnName="id2")
    })
   private Parent parent;
}
 
 
 
2-4-2. 복합키와 식별 관계
 
n  아래의 경우 부모테이블의 키가 자식테이블의 칼럼으로 참조되는데 식별관계이다. 즉 부모테이블의 PK가 자식테이블에 외래키(FK)로 참조될 때 자식의 기본키(PK)로 참조된다.
n  @EmbeddedId를 식별관계로 매핑하기 위해서는 @MapsId를 지정해야 하고 속성값으로는 @Embeddedable로 지정된 식별자에서 참조하는 연관객체의 기본키를 지정하면 된다.
 

 
@Entity
public class Child {
   @EmbeddedId
   private ChildKey id;
          
   @ManyToOne
   @JoinColumns({
     @JoinColumn(name="parent_id1", referencedColumnName="id1"),
     @JoinColumn(name="parent_id2", referencedColumnName="id2")
   })
   //Embeddedable로 지정한 식별자의 기본키필드지정
   //PK(키값)으로 매핑됨을 의미한다.
   @MapsId("parentKey") 
   private Parent parent;
 
@Embeddedable
public static class ChildKey implements Serializable {
   private ParentKey parentKey;          
    @Column
    private String id;
    //getter, setter, equals, hashCode는구현해야
   }
}

[JPA강좌,Querydsl쿼리사용법정리]쿼리(SQL)사용하는방법정리(JPQL, Querydsl, Creteria쿼리,Native SQL)

첨부파일 확인 부탁드립니다.

[JPA,JPQL강좌]Spring Data JPA에서 Native SQL사용하기,@Query 어노테이션에 nativeQuery=true라고 하면 된다. 물론 DB에서 사용하는 SQL형식으로 쿼리를 사용할 수 있다.

//제너릭 인터페이스
public interface EmpRepository<T> extends Repository<T, Long>
{
//Native SQL, SQL구문은 JPQL형태가 아니라 DB에서 사용하는 SQL형식을 쓰면 된다.
//nativeQuery 값의 default는 false
//#entityName은 SpEL 표현이며 위 Repository<T, Long>의 T객체를 가리킨다.
           @Query(value="select * from #{#entityName} e where e.ename = ?1",
                        nativeQuery=true)
           List<Emp> findByEname(String ename);
          
// 아래는 Native SQL 아님
           @Query(value="select ename, job, sal from Emp e where e.sal > ?1 and e.sal < ?2 ")
           List<Emp> findBySalRange(Long sal1, Long sal2);
}
[스프링JPA교육기초실습]QueryDSL4.0.8,기본쿼리,서브쿼리,조인,페이징@Query,NamedQuery실습,PageRequest,JPAQuery,JPA__EXPRESSION__s,limit,fetch,exists,innerJoin,JPAUpdateClause,JPADeleteClause,orderBy 

첨부 파일 참조하세요. 

Spring Boot, Spring Data JPA, Spring WEB MVC, QueryDSL @NamedQuery, @Query, 메소드 이름으로 쿼리생성(Query Method), 페이징처리, 서브쿼리, 조인 기본 예제를 마리아DB를 이용하여 작성해 보자. 

QueryDSL  MAVEN 설정은 아래 URL에서 참조 
http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=543 

마리아 DB 설치는 다음 URL 참조 
http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=524 

롬복(Lombok)설치는 다음 URL 참조 
http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=561 

감사합니다. 
[스프링JPA강좌,Querydsl]SQLQueryFactory(MAVEN설정,서브쿼리,조인,orderby,groupBy, insert/update 배치쿼리,partitionBy, over), 스프링부트

첨부 파일 참조하셔서 천천히 따라해 보세요~ 
감사합니다. 
[JPA교육,엔티티매핑]N:1단방향 연관관계,@ManyToOne, @JoinTable, @OnDelete, @ForeignKey

n  사원, 부서관계 처럼 N:1 형태의 관계를 이야기 하는데 Emp에서 Dept의 칼럼을 참조하는 경우이다. (하나의 부서에는 사원이 N개, 하나의 사원은 하나의 부서에만 속하는 관계)

첨부 파일 참조하세요.
감사합니다.
[JPA,Querydsl강좌]SQLQueryFactory,JPA,조인,서브쿼리,그룹핑,정렬예문(JPA, NativeSQL) 

SQLQueryFactory를 이용하면 자바쪽에 엔티티를 만들지 않고 DB로 쿼리 할 수 있다. 
(물론 이를 위해 쿼리타입이라는 클래스는 만들어져 있어야 한다.) 

기존 NativeSQL을 이용하여 DB의 SQL구문형식대로 만들어 쿼리했던 방식을 JPA의 메소드 기반으로 쿼리할 수 있는 장점이 있다. 

간단히 예문을 보자. 

// Emp, Dept를 조인하여 사원명, 부서명 출력, 5길동은 부서가 없으므로 출력안됨 
List<Tuple> emps1 = queryFactory.select(emp.ename, dept.dname) 
.from(emp) 
.innerJoin(dept) 
.on(emp.deptno.eq(dept.deptno)) 
.fetch(); 

for (Tuple row : emps1) { 
System.out.println(row.get(emp.ename) + ":" + row.get(dept.dname)); 
} 
System.out.println("----------------2"); 

// Emp, Dept를 조인하여 사원명, 부서명 출력, 부서없는 5길동도 출력 
List<Tuple> emps2 = queryFactory.select(emp.ename, dept.dname) 
.from(emp) 
.leftJoin(dept) 
.on(emp.deptno.eq(dept.deptno)) 
.fetch(); 

for (Tuple row : emps2) { 
System.out.println(row.get(emp.ename) + ":" + row.get(dept.dname)); 
} 
System.out.println("----------------3"); 

// Emp 테이블에서 부서별로 그룹핑하여 부서명, 급여합 출력 
// 단 급여평균이 2000 이상인 부서만 
List<Tuple> emps3 = queryFactory.select(dept.dname, emp.sal.sum()) 
.from(emp) 
.innerJoin(dept) 
.on(emp.deptno.eq(dept.deptno)) 
.groupBy(emp.deptno) 
.having(emp.sal.avg().gt(2000))
.fetch(); 

for (Tuple row : emps3) { 
System.out.println(row.get(dept.dname) + ":" 
                    + row.get(1, Long.class)); 
} 
System.out.println("----------------4"); 

//Emp 테이블에서 급여최소인 사원의 모든 칼럼 추출 
SEmp e = new SEmp("e"); 
List<Tuple> emps4 = queryFactory.select(emp.all()) 
                .from(emp) 
            .where(emp.sal.eq( 
              SQL__EXPRESSION__s.select(e.sal.min()).from(e))) 
            .fetch(); 
for (Tuple row : emps4) { 
System.out.println(row.get(emp.ename) + ":" 
                    + row.get(emp.sal)); 
} 
System.out.println("----------------4"); 

//Emp 테이블에서 job별 최소급여 사원의 ename, job, sal 출력 
List<Tuple> emps5 = queryFactory.select(emp.ename, emp.job, emp.sal) 
      .from(emp) 
      .where(emp.sal.eq( 
            SQL__EXPRESSION__s.select(e.sal.min()).from(e) 
              .where(emp.job.eq(e.job)))) 
  .fetch(); 

for (Tuple row : emps5) { 
System.out.println(row.get(emp.job) + ":" 
                    + row.get(emp.ename) + ":" 
        + row.get(emp.sal)); 
} 
System.out.println("----------------5"); 

//"1길동" 사원과 같은 부서에 있는 사원중 최대급여 사원의 이름 및 급여, 부서명출력 
List<Tuple> emps6 = queryFactory.select(emp.ename, emp.sal, dept.dname) 
.from(emp) 
.innerJoin(dept).on(emp.deptno.eq(dept.deptno)) 
.where(emp.deptno.eq( 
SQL__EXPRESSION__s 
.select(e.deptno) 
.from(e) 
.where(e.ename.eq("1길동"))
    ).and(emp.sal.eq( 
    SQL__EXPRESSION__s 
    .select(e.sal.max()) 
    .from(e) 
    .where(emp.deptno.eq(e.deptno)) 
    ))) 
                .fetch(); 

for (Tuple row : emps6) { 
System.out.println(row.get(emp.ename) + ":" 
                    + row.get(emp.sal) + ":" 
        + row.get(dept.dname)); 
} 
System.out.println("----------------6");