2016-07-12 2 views
2

외래 키를 기반으로 필드 자동 증가가 가능합니까? JPA (Hibernate)와 Oracle DB를 사용하여이 작업을 수행하고 싶습니다. 나는 MySQLInnoDB 엔진으로는 불가능하다고 읽었습니다.외래 키 (JPA, Hibernate, Oracle DB)에 기반한 증가 필드

그것은 꽤 많은 다음과 같은 질문에 같은 :

  • mysql-auto-increment-based-on-foreign-key
    • 내가 필요 정확히이지만, 슬프게도 아무 대답이 없다.

      구체적인 예로는 간단한 예를 생각해보십시오. 각 Student에는 Book이 여러 개 있습니다. Book에는 기본 키 (일반 증분)가 있지만 followUpNumber도 있습니다. 이 번호는 1에서 시작하여 각각 Book에서 Student에 자동 증분됩니다. 모든 Student의 의미는 Book이고 그 중 followUpNumber은 매시간 1에서 시작합니다. 학생

    • followup_number에서 시작 분야 인에 외부 키 인를 student_id

      |------|------------|-----------------| 
      | id | student_id | followup_number | 
      |------|------------|-----------------| 
      | 1 |  1  |  1  | 
      | 2 |  1  |  2  | 
      | 3 |  1  |  3  | 
      | 4 |  2  |  1  | 
      | 5 |  1  |  4  | 
      | 6 |  1  |  5  | 
      | 7 |  2  |  2  | 
      | 8 |  3  |  1  | 
      | 9 |  3  |  2  | 
      |------|------------|-----------------| 
      
      • ID 기본 키
      • 인 : 여기에 내가 무엇을 의미하는지 표시하는 Book 테이블입니다 1 개당 1 개 student_id

      기본 키 입력란에 배치 할 필요가없는 맞춤형 @GeneratedValue 전략이 ​​있습니까? 현재 내 솔루션은 새로운 Book을 추가하기 전이고 모든 Book 초를 반복하고 가장 높은 followup_number를 가져 와서 해당 번호 +1을 새 책에 할당합니다. 그러나 나는 이것을하기위한 더 깨끗하고 우아한 방법이 있어야한다고 생각한다.

    +0

    데이터베이스 트리거가 마음에 온다, 그것은 JPA에 의해 해결 될 필요가 없습니다. 그러나 나는 JPA 지향 솔루션을보고 싶어 할 것입니다. – Gimby

    답변

    2

    @OrderColumn 주석을 사용할 수 있습니다.

    공공 @interface의 OrderColumn

    는 목록의 지속적인 질서를 유지 에 사용되는 열을 지정합니다. 지속성 공급자는 이며 검색시 주문을 유지 관리하고 데이터베이스는 입니다. 지속성 공급자는 삽입을 반영하기 위해 데이터베이스로 플러시 할 때 순서를 업데이트하고 목록에 영향을주는 삭제 또는 순서 변경을 업데이트해야합니다.

    OrderColumn 주석은 OneToMany 또는 ManyToMany 관계 또는 요소 컬렉션에 지정됩니다.OrderColumn 주석 은 주문할 콜렉션을 참조하는 관계의 측면에서 지정됩니다. 주문 열은 개체 또는 embeddable 클래스 상태의 일부로 표시되지 않습니다.

    OrderBy 주석은 지속 상태로 표시되고 응용 프로그램에 의해 유지 관리되는 주문에 사용해야합니다. OrderBy Annotation은 OrderColumn이 지정된 경우 사용되지 않습니다.

    주문 열은 필수 유형이어야합니다. 지속성 공급자 은 연관 또는 요소 컬렉션을 업데이트 할 때 주문 열의 값을 연속적으로 (비 희소하게) 정렬합니다.

    @Entity 
    @Table(name="STUDENT") 
    @SequenceGenerator(name="student_seq", initialValue=1, 
            allocationSize=10,sequenceName="STUDDENT_SEQ") 
    public class Student { 
    
        @Id 
        @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="student_seq") 
        private Long Id; 
    
        @Column(name="NAME") 
        private String name; 
    
        @OneToMany(cascade = CascadeType.ALL, mappedBy="student") 
        @OrderColumn(name="FOLLOWUP_NUMBER") 
        private List<Book> books = new ArrayList<>(); 
    
        ............... 
        ............... 
    } 
    
    : 첫 번째 요소의 위해 열 값 유일한 단점은 첫번째 요소의 수가 1


    예시되지 0 있다는 0


    @Entity 
    @SequenceGenerator(name="book_seq", initialValue=1, 
            allocationSize=10, sequenceName="BOOK_SEQ") 
    public class Book { 
    
        @Id 
        @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="book_seq") 
        private Long id; 
    
        @ManyToOne 
        @JoinColumn(name="STUDENT_ID") 
        private Student student; 
    
        @Column(name="TITLE", nullable=false) 
        private String title; 
    
        .................. 
        .................. 
    } 
    

    ,210

    그리고이 간단한 테스트 케이스 :

    EntityTransaction tr = em.getTransaction(); 
    
    tr.begin(); 
    
    for (int j = 1; j < 10; j++) { 
        Student student = new Student("Student name " + j); 
        for (int i = 1; i <= 10; i++) { 
         student.getBooks().add(new Book("Some book" + i, student)); 
        } 
        em.persist(student); 
    } 
    
    tr.commit(); 
    

    는 다음과 같은 테이블을 생성 (오라클 12C 테스트 5.2 최대 절전 모드) :

    select * from student; 
        ID NAME    
    ----- -------------------- 
        1 Student name 1  
        2 Student name 2  
        3 Student name 3  
        4 Student name 4 
        ....... 
        ....... 
    

    select * from book 
    order by student_id, followup_number; 
        ID TITLE    STUDENT_ID FOLLOWUP_NUMBER 
    ----- -------------------- ---------- --------------- 
        1 Some book1     1   0 
        2 Some book2     1   1 
        3 Some book3     1   2 
        4 Some book4     1   3 
        5 Some book5     1   4 
        6 Some book6     1   5 
        7 Some book7     1   6 
        8 Some book8     1   7 
        9 Some book9     1   8 
        10 Some book10     1   9 
        11 Some book1     2   0 
        12 Some book2     2   1 
        13 Some book3     2   2 
        14 Some book4     2   3 
        15 Some book5     2   4 
        16 Some book6     2   5 
        17 Some book7     2   6 
        18 Some book8     2   7 
        19 Some book9     2   8 
        20 Some book10     2   9 
        21 Some book1     3   0 
        22 Some book2     3   1 
        23 Some book3     3   2 
        ........ 
        ........ 
    

    는 성능이있을 수 있습니다 또 다른 단점은, 각 책에 대해 Hibernate가 두개의 SQL 명령을 생성했기 때문이다 - 하나의 insert와 o FOLLOWUP_NUMBER 컬럼의 업데이트.
    어떤 책이 삭제되면 Hibernate는 주어진 학생의 모든 숫자를 다시 생성하고 남아있는 모든 책에 대해 FOLLOWUP_NUMBER 열의 업데이트를 실행합니다.


    편집


    하지만 날 귀찮게하는 것은 "순서 열이 엔티티 또는 임베드 클래스의 상태의 일부로 볼 수 없습니다."입니다. 데이터는 마치 DB 에서처럼 을 좋아하지만 내 엔티티에 반영되지 않습니다.나는 이것이 JPA에 possibe 경우

    내가 모르는이 FOLLOWUP_NUMBER을 활용하고자 싶지만, 최대 절전 모드 확장 @Formula이 경우에 사용할 수 있지만 :

    class Book{ 
        ....... 
        ....... 
    
        @Formula(value="FOLLOWUP_NUMBER") 
        private Long followUpNumber; 
    
        public Long getFollowUpNumber() { 
         return followUpNumber; 
        } 
    
        ........ 
        ........ 
    } 
    

    이를 다음 결과

    Query query = em.createQuery(
        "Select b FROM Book b JOIN b.student s " + 
        "WHERE s.name = :studentname AND b.followUpNumber = :follownbr" 
    ); 
    query.setParameter("studentname", "Student name 6"); 
    query.setParameter("follownbr", Long.valueOf(4)); 
    Book book = (Book)query.getSingleResult(); 
    
    System.out.println("Found book = " + book.getTitle()); 
    System.out.println("book follow nbr= " + book.getFollowUpNumber()); 
    

    제공합니다 :

    계산 필드에도, 예를 들면, 아래의 테스트 케이스를 조회 할 수있다 17,451,515,
    Found book = Some book5 
    book follow nbr= 4 
    

    및 최대 절전 모드가 그 책 찾기 위해 아래의 SQL을 사용하여 삽입에

    select 
         book0_.id as id1_0_, 
         book0_.STUDENT_ID as STUDENT_ID3_0_, 
         book0_.TITLE as TITLE2_0_, 
         book0_.FOLLOWUP_NUMBER as formula0_ 
        from 
         Book book0_ 
        inner join 
         STUDENT student1_ 
          on book0_.STUDENT_ID=student1_.Id 
        where 
         student1_.NAME=? 
         and book0_.FOLLOWUP_NUMBER=? 
    
    +0

    JPA에는 가능한 해결책이 있습니다. 하지만 저를 괴롭히는 것은 * "주문 열은 엔티티 또는 임베딩 클래스의 상태의 일부로 표시되지 않습니다."*. 데이터는 DB에서와 마찬가지로 표시되지만 내 엔터티에는 반영되지 않습니다. 나는이 'FOLLOWUP_NUMBER'을 사용하고 싶습니다. – Jaims

    +0

    이 경우'@ Formula' 확장을 사용할 수 있습니다. 예제에 답을 추가했습니다. – krokodilko