@OrderColumn注釈を使用することができます。
公共@interface OrderColumn
は、リストの持続的な秩序を維持 に使用される列を指定します。持続性プロバイダは、検索時および データベースで注文の維持を担当する です。持続性プロバイダは、挿入を反映するためにデータベースにフラッシュするときに の順序を更新し、 の削除、または並べ替えがリストに影響します。
OrderColumnアノテーションは、OneToManyまたはManyToMany リレーションシップまたは要素コレクションで指定されます。OrderColumn注釈 は、オーダーする コレクションを参照する関係の側で指定されています。指図列は、 エンティティまたは埋め込み可能クラスの状態の一部として表示されません。
OrderBy注釈は、 永続状態として表示され、アプリケーションによって管理されている発注に使用する必要があります。 OrderBy 注釈は、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<>();
...............
...............
}
:最初の要素の 順序列の値は0
唯一の欠点は、最初の要素の数は、例えば0ではなく1
であることです
@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;
..................
..................
}
そして、この単純なテスト・ケース:
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が2つのSQLコマンドを生成するからです。 FOLLOWUP_NUMBER
列の更新。
さらに悪いことに、一部の本が削除されると、Hibernateは特定の生徒のすべての番号を再度生成し、残っているすべての書籍についてFOLLOWUP_NUMBER
列の更新を起動します。
EDIT
しかし、どのような私を気にすることは「注文の列がエンティティまたは埋め込み可能なクラスの 状態の一部として表示されません。」です。データはちょうど私が をDBで好きだが、それは私のエンティティに反映されていません。私は このFOLLOWUP_NUMBER
の利用をしたいのですが、これは、JPAでpossibeある場合、私は知りませんが、Hibernateの拡張@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());
は、以下の結果を与え
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=?
挿入時にデータベース・トリガーが頭に浮かぶ、それはJPAが解決しようとする必要はありません。しかし、私はJPA指向のソリューションを知りたいと思っています。 – Gimby