Entries tagged [jpa]
Just try to use OrderColumn
TweetPosted on Thursday Jan 30, 2014 at 02:09PM in Technology
It sounds convenience so I just tried it.
Environment
- WildFly 8.0.0.Final
- Hibernate 4.3.1
- PostgreSQL 9.2.4
- postgresql-9.3-1100.jdbc41.jar
Does Hibernate require intersection entity for @OrderColumn?
According to [2], it said that @OrderColumn doesn't work with relations like that:
Parent side
@OneToMany(mappedBy = "dept") @OrderColumn(name = "pos") private List<Employee> employees;
Child side
@ManyToOne @JoinColumn(nullable = false) private Dept dept;
I found [1], and it said something like that it working now with recent versions.
And, like said at [2], when I delete mappedBy, it makes intersection entity (dept_employee).
Make example project
Whole project resources are available in GitHub.
Codes that I will mention later are easy to find in these files:
Entities in the project
Test data
Available in GitHub.
Data entry to empty table
log
19:51:55,703 DEBUG [org.hibernate.SQL] (default task-2) select nextval ('hibernate_sequence') 19:51:55,704 DEBUG [org.hibernate.SQL] (default task-2) select nextval ('hibernate_sequence') 19:51:55,705 DEBUG [org.hibernate.SQL] (default task-2) select nextval ('hibernate_sequence') 19:51:55,706 DEBUG [org.hibernate.SQL] (default task-2) select nextval ('hibernate_sequence') 19:51:55,712 DEBUG [org.hibernate.SQL] (default task-2) insert into Dept (deptName, id) values (?, ?) 19:51:55,714 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [1] as [VARCHAR] - [Finance] 19:51:55,714 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [2] as [BIGINT] - [1] 19:51:55,716 DEBUG [org.hibernate.SQL] (default task-2) insert into Employee (dept_id, firstName, lastName, pos, id) values (?, ?, ?, ?, ?) 19:51:55,716 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [1] as [BIGINT] - [1] 19:51:55,716 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [2] as [VARCHAR] - [Taro] 19:51:55,717 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [3] as [VARCHAR] - [Yamada] 19:51:55,717 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [4] as [INTEGER] - [null] 19:51:55,717 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [5] as [BIGINT] - [2] 19:51:55,719 DEBUG [org.hibernate.SQL] (default task-2) insert into Employee (dept_id, firstName, lastName, pos, id) values (?, ?, ?, ?, ?) 19:51:55,719 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [1] as [BIGINT] - [1] 19:51:55,719 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [2] as [VARCHAR] - [Jiro] 19:51:55,719 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [3] as [VARCHAR] - [Suzuki] 19:51:55,719 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [4] as [INTEGER] - [null] 19:51:55,719 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [5] as [BIGINT] - [3] 19:51:55,720 DEBUG [org.hibernate.SQL] (default task-2) insert into Employee (dept_id, firstName, lastName, pos, id) values (?, ?, ?, ?, ?) 19:51:55,720 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [1] as [BIGINT] - [1] 19:51:55,720 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [2] as [VARCHAR] - [Saburo] 19:51:55,720 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [3] as [VARCHAR] - [Tanaka] 19:51:55,721 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [4] as [INTEGER] - [null] 19:51:55,721 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [5] as [BIGINT] - [4] 19:51:55,721 DEBUG [org.hibernate.SQL] (default task-2) update Employee set pos=? where id=? 19:51:55,721 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [1] as [INTEGER] - [0] 19:51:55,722 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [2] as [BIGINT] - [2] 19:51:55,723 DEBUG [org.hibernate.SQL] (default task-2) update Employee set pos=? where id=? 19:51:55,723 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [1] as [INTEGER] - [1] 19:51:55,723 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [2] as [BIGINT] - [3] 19:51:55,724 DEBUG [org.hibernate.SQL] (default task-2) update Employee set pos=? where id=? 19:51:55,724 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [1] as [INTEGER] - [2] 19:51:55,724 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-2) binding parameter [2] as [BIGINT] - [4]
table
jpatest=# select * from dept ; id | deptname ----+---------- 1 | Finance (1 row) jpatest=# select * from employee ; id | firstname | lastname | pos | dept_id ----+-----------+----------+-----+--------- 2 | Taro | Yamada | 0 | 1 3 | Jiro | Suzuki | 1 | 1 4 | Saburo | Tanaka | 2 | 1 (3 rows) jpatest=#
Add an employee (didn't work correctly)
log
20:07:13,014 DEBUG [org.hibernate.SQL] (default task-8) select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 20:07:13,015 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [1] as [BIGINT] - [1] 20:07:13,015 TRACE [org.hibernate.type.descriptor.sql.BasicExtractor] (default task-8) extracted value ([deptName2_0_0_] : [VARCHAR]) - [Finance] 20:07:13,016 TRACE [org.hibernate.type.CollectionType] (default task-8) Created collection wrapper: [org.nailedtothex.jpatest.ordercolumn.Dept.employees#1] 20:07:13,016 DEBUG [org.hibernate.SQL] (default task-8) select nextval ('hibernate_sequence') 20:07:13,022 DEBUG [org.hibernate.SQL] (default task-8) insert into Employee (dept_id, firstName, lastName, pos, id) values (?, ?, ?, ?, ?) 20:07:13,023 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [1] as [BIGINT] - [1] 20:07:13,023 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [2] as [VARCHAR] - [Jane] 20:07:13,023 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [3] as [VARCHAR] - [Doe] 20:07:13,023 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [4] as [INTEGER] - [null] 20:07:13,023 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [5] as [BIGINT] - [1] 20:07:13,024 DEBUG [org.hibernate.SQL] (default task-8) update Employee set pos=? where id=? 20:07:13,024 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [1] as [INTEGER] - [0] 20:07:13,024 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [2] as [BIGINT] - [1]
table
jpatest=# select * from dept; id | deptname -----+---------- 101 | Finance (1 row) jpatest=# select * from employee ; id | firstname | lastname | pos | dept_id -----+-----------+----------+-----+--------- 201 | Taro | Yamada | 0 | 101 202 | Jiro | Suzuki | 1 | 101 203 | Saburo | Tanaka | 2 | 101 1 | Jane | Doe | 0 | 101 (4 rows) jpatest=#
- Hibernate doesn't fetch max pos, consequently, pos of Jane Doe assigned pos 0 that duplicated.
Add an employee (revised)
- To overcome the problem which above-mentioned, force Hibernate to fetch collections before addition of new entity through invoke size() method.
log
20:22:23,748 DEBUG [org.hibernate.SQL] (default task-6) select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 20:22:23,748 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [BIGINT] - [101] 20:22:23,749 DEBUG [org.hibernate.SQL] (default task-6) select employees0_.dept_id as dept_id5_0_0_, employees0_.id as id1_1_0_, employees0_.pos as pos4_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id5_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_, employees0_.pos as pos4_1_1_ from Employee employees0_ where employees0_.dept_id=? 20:22:23,750 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [BIGINT] - [101] 20:22:23,752 DEBUG [org.hibernate.SQL] (default task-6) select nextval ('hibernate_sequence') 20:22:23,760 DEBUG [org.hibernate.SQL] (default task-6) insert into Employee (dept_id, firstName, lastName, pos, id) values (?, ?, ?, ?, ?) 20:22:23,760 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [BIGINT] - [101] 20:22:23,760 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [2] as [VARCHAR] - [Jane] 20:22:23,760 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [3] as [VARCHAR] - [Doe] 20:22:23,761 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [4] as [INTEGER] - [null] 20:22:23,761 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [5] as [BIGINT] - [1] 20:22:23,762 DEBUG [org.hibernate.SQL] (default task-6) update Employee set pos=? where id=? 20:22:23,762 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [INTEGER] - [0] 20:22:23,762 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [2] as [BIGINT] - [201] 20:22:23,763 DEBUG [org.hibernate.SQL] (default task-6) update Employee set pos=? where id=? 20:22:23,763 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [INTEGER] - [1] 20:22:23,763 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [2] as [BIGINT] - [202] 20:22:23,763 DEBUG [org.hibernate.SQL] (default task-6) update Employee set pos=? where id=? 20:22:23,763 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [INTEGER] - [2] 20:22:23,763 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [2] as [BIGINT] - [203] 20:22:23,764 DEBUG [org.hibernate.SQL] (default task-6) update Employee set pos=? where id=? 20:22:23,764 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [INTEGER] - [3] 20:22:23,764 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [2] as [BIGINT] - [1]
table
jpatest=# select * from employee ; id | firstname | lastname | pos | dept_id -----+-----------+----------+-----+--------- 201 | Taro | Yamada | 0 | 101 202 | Jiro | Suzuki | 1 | 101 203 | Saburo | Tanaka | 2 | 101 1 | Jane | Doe | 3 | 101 (4 rows) jpatest=#
- Hibernate recognized maximum pos and Jane Doe assigned correct pos.
Delete an employee
log
20:47:53,429 DEBUG [org.hibernate.SQL] (default task-14) select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 20:47:53,429 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [1] as [BIGINT] - [101] 20:47:53,430 DEBUG [org.hibernate.SQL] (default task-14) select employees0_.dept_id as dept_id5_0_0_, employees0_.id as id1_1_0_, employees0_.pos as pos4_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id5_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_, employees0_.pos as pos4_1_1_ from Employee employees0_ where employees0_.dept_id=? 20:47:53,430 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [1] as [BIGINT] - [101] 20:47:53,435 DEBUG [org.hibernate.SQL] (default task-14) update Employee set pos=? where id=? 20:47:53,436 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [1] as [INTEGER] - [0] 20:47:53,436 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [2] as [BIGINT] - [201] 20:47:53,436 DEBUG [org.hibernate.SQL] (default task-14) update Employee set pos=? where id=? 20:47:53,436 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [1] as [INTEGER] - [1] 20:47:53,436 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [2] as [BIGINT] - [203] 20:47:53,439 DEBUG [org.hibernate.SQL] (default task-14) delete from Employee where id=? 20:47:53,439 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [1] as [BIGINT] - [202]
table
jpatest=# select * from dept ; id | deptname -----+---------- 101 | Finance (1 row) jpatest=# select * from employee ; id | firstname | lastname | pos | dept_id -----+-----------+----------+-----+--------- 201 | Taro | Yamada | 0 | 101 203 | Saburo | Tanaka | 1 | 101 (2 rows) jpatest=#
Swap order
log
21:02:05,979 DEBUG [org.hibernate.SQL] (default task-1) select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 21:02:05,980 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [1] as [BIGINT] - [101] 21:02:05,981 DEBUG [org.hibernate.SQL] (default task-1) select employees0_.dept_id as dept_id5_0_0_, employees0_.id as id1_1_0_, employees0_.pos as pos4_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id5_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_, employees0_.pos as pos4_1_1_ from Employee employees0_ where employees0_.dept_id=? 21:02:05,981 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [1] as [BIGINT] - [101] 21:02:05,983 FINE [org.nailedtothex.jpatest.ordercolumn.OrderColumnTestDataManipulator] (default task-1) [Employee [id=201, firstName=Taro, lastName=Yamada, pos=0, dept=101], Employee [id=202, firstName=Jiro, lastName=Suzuki, pos=1, dept=101], Employee [id=203, firstName=Saburo, lastName=Tanaka, pos=2, dept=101]] 21:02:05,983 FINE [org.nailedtothex.jpatest.ordercolumn.OrderColumnTestDataManipulator] (default task-1) [Employee [id=201, firstName=Taro, lastName=Yamada, pos=0, dept=101], Employee [id=203, firstName=Saburo, lastName=Tanaka, pos=2, dept=101], Employee [id=203, firstName=Saburo, lastName=Tanaka, pos=2, dept=101]] 21:02:05,984 FINE [org.nailedtothex.jpatest.ordercolumn.OrderColumnTestDataManipulator] (default task-1) [Employee [id=201, firstName=Taro, lastName=Yamada, pos=0, dept=101], Employee [id=203, firstName=Saburo, lastName=Tanaka, pos=2, dept=101], Employee [id=202, firstName=Jiro, lastName=Suzuki, pos=1, dept=101]] 21:02:05,987 DEBUG [org.hibernate.SQL] (default task-1) update Employee set pos=? where id=? 21:02:05,987 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [1] as [INTEGER] - [0] 21:02:05,987 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [2] as [BIGINT] - [201] 21:02:05,988 DEBUG [org.hibernate.SQL] (default task-1) update Employee set pos=? where id=? 21:02:05,988 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [1] as [INTEGER] - [1] 21:02:05,988 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [2] as [BIGINT] - [203] 21:02:05,989 DEBUG [org.hibernate.SQL] (default task-1) update Employee set pos=? where id=? 21:02:05,989 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [1] as [INTEGER] - [2] 21:02:05,989 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-1) binding parameter [2] as [BIGINT] - [202]
table
jpatest=# select * from dept ; id | deptname -----+---------- 101 | Finance (1 row) jpatest=# select * from employee ; id | firstname | lastname | pos | dept_id -----+-----------+----------+-----+--------- 201 | Taro | Yamada | 0 | 101 203 | Saburo | Tanaka | 1 | 101 202 | Jiro | Suzuki | 2 | 101 (3 rows) jpatest=#
Retrieve from unordered table
log
21:13:55,544 DEBUG [org.hibernate.SQL] (default task-4) select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 21:13:55,545 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-4) binding parameter [1] as [BIGINT] - [101] 21:13:55,546 DEBUG [org.hibernate.SQL] (default task-4) select employees0_.dept_id as dept_id5_0_0_, employees0_.id as id1_1_0_, employees0_.pos as pos4_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id5_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_, employees0_.pos as pos4_1_1_ from Employee employees0_ where employees0_.dept_id=? 21:13:55,546 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-4) binding parameter [1] as [BIGINT] - [101] 21:13:55,548 FINE [org.nailedtothex.jpatest.ordercolumn.OrderColumnTestDataManipulator] (default task-4) [Employee [id=201, firstName=Taro, lastName=Yamada, pos=0, dept=101], Employee [id=202, firstName=Jiro, lastName=Suzuki, pos=1, dept=101], Employee [id=203, firstName=Saburo, lastName=Tanaka, pos=2, dept=101]]
table
jpatest=# select employees0_.dept_id as dept_id5_0_0_, employees0_.id as id1_1_0_, employees0_.pos as pos4_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id5_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_, employees0_.pos as pos4_1_1_ from Employee employees0_ where employees0_.dept_id=101; dept_id5_0_0_ | id1_1_0_ | pos4_0_ | id1_1_1_ | dept_id5_1_1_ | firstnam2_1_1_ | lastname3_1_1_ | pos4_1_1_ ---------------+----------+---------+----------+---------------+----------------+----------------+----------- 101 | 203 | 2 | 203 | 101 | Saburo | Tanaka | 2 101 | 201 | 0 | 201 | 101 | Taro | Yamada | 0 101 | 202 | 1 | 202 | 101 | Jiro | Suzuki | 1 (3 rows) jpatest=#
- Hibernate executed a query that not contains ORDER BY, and returned unordered result set, but I got correctly ordered list (did Java sorted it?).
Reverse the order
log
22:23:11,950 DEBUG [org.hibernate.SQL] (default task-9) select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 22:23:11,950 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [BIGINT] - [101] 22:23:11,951 DEBUG [org.hibernate.SQL] (default task-9) select employees0_.dept_id as dept_id5_0_0_, employees0_.id as id1_1_0_, employees0_.pos as pos4_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id5_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_, employees0_.pos as pos4_1_1_ from Employee employees0_ where employees0_.dept_id=? 22:23:11,951 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [BIGINT] - [101] 22:23:11,956 DEBUG [org.hibernate.SQL] (default task-9) update Employee set pos=? where id=? 22:23:11,957 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [INTEGER] - [0] 22:23:11,957 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [2] as [BIGINT] - [203] 22:23:11,957 DEBUG [org.hibernate.SQL] (default task-9) update Employee set pos=? where id=? 22:23:11,957 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [INTEGER] - [1] 22:23:11,957 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [2] as [BIGINT] - [202] 22:23:11,958 DEBUG [org.hibernate.SQL] (default task-9) update Employee set pos=? where id=? 22:23:11,958 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [INTEGER] - [2] 22:23:11,958 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [2] as [BIGINT] - [201]
table
jpatest=# select * from employee ; id | firstname | lastname | pos | dept_id -----+-----------+----------+-----+--------- 203 | Saburo | Tanaka | 0 | 101 202 | Jiro | Suzuki | 1 | 101 201 | Taro | Yamada | 2 | 101 (3 rows) jpatest=#
Conclusion
Pros
- It brings powerful mechanism that developer can reduce some annoying codes to maintain order of the list.
Cons
- It executes bunch of inefficient queries.
- Through considering above queries, maybe use of unique index of order column is impossible.
Remarks
- Not bad for such as low-traffic internal systems.
- To OrderColumn work correctly, we have to keep all elements fetched when modify the list.
References
Tags: jpa
Entity Graphを使ってみる
TweetPosted on Sunday Jan 26, 2014 at 04:05PM in Technology
JPA2.1の新機能Entity Graphを使ってみます。SELECT文を実行するときにどこまで階層を掘り下げて拾ってくるかを指定することができるようになり、むだにManaged状態のときにsize()を呼び出したりしなくてよくなる仕組みのようです。
環境
- Hibernate 4.3.0.Final
- WildFly8.0.0.CR1
- Oracle JDK7u51
- postgresql-9.3-1100.jdbc41.jar
- PostgreSQL 9.2.4
使い方
- エンティティの階層を表すEntity Graphを作ります。JPQLのような名前付きの静的なものとして作っておく他に、動的にコードから作ることも可能。Canonical MetaModelも使えるようです。
- Query#setHint()メソッドを使ってEntity Graphを渡してやってからクエリを実行します。ヒント名には2つあり、どちらを使うかで以下のように動作が変わります
- javax.persistence.fetchgraph: Entity Graphに含まれるフィールドのみロードされる。含まれないフィールドはロードされない。Entity Graphに含まれないフィールドは全てLAZY扱いになる
- javax.persistence.loadgraph: Entity Graphに含まれるフィールドはLAZYであってもロードされる。含まれないフィールドはそれぞれのフィールドの設定による
前提条件
NativeQueryで関連持ちエンティティをSELECTしてみるで使った資源を使います。エンティティはこれです
試してみる
javax.persistence.fetchgraph
Entity Graphを作る
Employeeクラスにこんなアノテーションを付けます
@NamedEntityGraph( name = "onlyFirstNameAndLastName", attributeNodes = { @NamedAttributeNode("firstName"), @NamedAttributeNode("lastName")})
orm.xmlにクエリを定義
<named-query name="findEmployees"> <query><![CDATA[ SELECT e FROM Employee e ]]></query> </named-query>
テストメソッド
@Test @Transactional @UsingDataSet({"datasets/relativeSelect/dept.yml", "datasets/relativeSelect/employees.yml"}) public void select() throws Exception { EntityGraph<?> entityGraph = em.getEntityGraph("onlyFirstNameAndLastName"); dumpEmployeeList(em.createNamedQuery("findEmployees", Employee.class) .setHint("javax.persistence.fetchgraph", entityGraph) .getResultList()); } protected void dumpEmployeeList(List<Employee> employees){ for(Employee emp : employees){ System.out.printf(" emp: id=%d, firstName=%s, lastName=%s\n", emp.getId(), emp.getFirstName(), emp.getLastName()); } }
テストメソッドを実行
javax.persistence.fetchgraphを指定して、Entity GraphではfirstNameとlastNameのみ指定しているので、deptはロードされないと思っていたら…
17:27:12,991 INFO [stdout] (pool-2-thread-34) Hibernate: select employee0_.id as id1_1_, employee0_.dept_id as dept_id4_1_, employee0_.firstName as firstNam2_1_, employee0_.lastName as lastName3_1_ from Employee employee0_ 17:27:12,993 INFO [stdout] (pool-2-thread-34) Hibernate: select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 17:27:12,994 INFO [stdout] (pool-2-thread-34) Hibernate: select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 17:27:12,995 INFO [stdout] (pool-2-thread-34) emp: id=-1, firstName=Taro, lastName=Yamada 17:27:12,996 INFO [stdout] (pool-2-thread-34) emp: id=-2, firstName=Jiro, lastName=Suzuki 17:27:12,996 INFO [stdout] (pool-2-thread-34) emp: id=-3, firstName=Saburo, lastName=Tanaka
何故か普通に取ってきてますね。どうも無視されているような気が…。[2]にはエンティティグラフについても言及されているようなのだが未実装という事だろうか。あるいは、この機能はあくまでヒントであって実際にどうなるかはJPAプロバイダの実装によるとかそういう事なのか。
[1]を書いた人のサンプルを見るとEclipseLinkを使っているようなのでEclipseLinkなら期待通りの動作をするかもしれない。
[4]に起票されているが、どうもJPA仕様では強制されてないからバグではないと認識されているようだ。ううむ。
javax.persistence.loadgraph
Entity Graphを作る
Deptクラスにこんなアノテーションを付けます
@NamedEntityGraph( name = "loadEmployees", attributeNodes = { @NamedAttributeNode("employees")} )
orm.xmlにクエリを定義
<named-query name="findDeptsDistinct"> <query><![CDATA[ SELECT DISTINCT d FROM Dept AS d ]]></query> </named-query>
テストメソッド
@Test @Transactional @UsingDataSet({"datasets/relativeSelect/dept.yml", "datasets/relativeSelect/employees.yml"}) public void select() throws Exception { EntityGraph<?> entityGraph = em.getEntityGraph("loadEmployees"); dumpDeptList(em.createNamedQuery("findDeptsDistinct", Dept.class) .setHint("javax.persistence.loadgraph", entityGraph) .getResultList()); } protected void dumpEmployeeList(List<Employee> employees){ for(Employee emp : employees){ System.out.printf(" emp: id=%d, firstName=%s, lastName=%s\n", emp.getId(), emp.getFirstName(), emp.getLastName()); } } protected void dumpDeptList(List<Dept> list){ for(Dept dept : list){ System.out.printf("dept: id=%d, deptName=%s\n", dept.getId(), dept.getDeptName()); dumpEmployeeList(dept.getEmployees()); } }
テストメソッドを実行
21:03:35,540 INFO [stdout] (pool-2-thread-4) Hibernate: select distinct dept0_.id as id1_0_0_, employees1_.id as id1_1_1_, dept0_.deptName as deptName2_0_0_, employees1_.dept_id as dept_id4_1_1_, employees1_.firstName as firstNam2_1_1_, employees1_.lastName as lastName3_1_1_, employees1_.dept_id as dept_id4_0_0__, employees1_.id as id1_1_0__ from Dept dept0_ left outer join Employee employees1_ on dept0_.id=employees1_.dept_id 21:03:35,544 INFO [stdout] (pool-2-thread-4) dept: id=-1, deptName=Sales 21:03:35,545 INFO [stdout] (pool-2-thread-4) emp: id=-2, firstName=Jiro, lastName=Suzuki 21:03:35,545 INFO [stdout] (pool-2-thread-4) emp: id=-1, firstName=Taro, lastName=Yamada 21:03:35,545 INFO [stdout] (pool-2-thread-4) dept: id=-2, deptName=Legal 21:03:35,545 INFO [stdout] (pool-2-thread-4) emp: id=-3, firstName=Saburo, lastName=Tanaka
めでたくSELECT文が一回になりました。こっちは大丈夫そう。
その他
Entity Graphをorm.xmlで定義しようとすると例外が起きてしまい動作しません。「named-attribute-node.value is mandatory in XML overriding.」と言われます。書き方が悪いのか、あるいは他の原因があるのかは不明。またそのうち調べる。
参考文献
Tags: jpa
NativeQueryで複数のエンティティを同時にSELECTしつつconstructor-resultを使ってみる
TweetPosted on Sunday Jan 26, 2014 at 03:18PM in Technology
NativeQueryでconstructor-resultを使ってSELECTしてみるの続きです。2つのエンティティ分のデータを取得するSELECT文から、エンティティ2つに加えて、DTOクラスのオブジェクト1つをconstructor-resultを使って取得してみます。だからなんだって感じもしますが。
環境
- Hibernate 4.3.0.Final
- WildFly8.0.0.CR1
- Oracle JDK7u51
- postgresql-9.3-1100.jdbc41.jar
- PostgreSQL 9.2.4
何をするか
エンティティと関連の構造は前回と同じです。
今回は以下をSELECT一回で取ってきます
- Employeeエンティティ
- Deptエンティティ
- deptName, firstName, lastNameをフィールドにもつDTO
準備
配置図
図中で選択されている資源を作成または編集します。
- orm.xmlにNamedNativeQuery “findVarious” とResultSetMapping “variousResult” を追加します
- テストクラスVariousResultSelectTestを作ります
- DTOクラスEmployeeProfileを作ります
- テストデータは前回のを流用します
EmployeeProfile.java
package org.arquillian.example; public class EmployeeProfile { private String deptName; private String firstName; private String lastName; public EmployeeProfile(String deptName, String firstName, String lastName) { super(); this.deptName = deptName; this.firstName = firstName; this.lastName = lastName; } @Override public String toString() { return "EmployeeProfile [deptName=" + deptName + ", firstName=" + firstName + ", lastName=" + lastName + "]"; } }
orm.xml
<?xml version="1.0" encoding="UTF-8"?> <entity-mappings version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"> <named-native-query name="findVarious" result-set-mapping="variousResult"> <query><![CDATA[ SELECT emp.id, emp.firstName, emp.lastName, emp.dept_id, dep.deptName FROM Employee AS emp, Dept AS dep WHERE emp.dept_id = dep.id ]]></query> </named-native-query> <sql-result-set-mapping name="variousResult"> <entity-result entity-class="org.arquillian.example.Employee"/> <entity-result entity-class="org.arquillian.example.Dept"> <field-result name="id" column="dept_id"/> <field-result name="deptName" column="deptName"/> </entity-result> <constructor-result target-class="org.arquillian.example.EmployeeProfile"> <column name="deptName" class="java.lang.String" /> <column name="firstName" class="java.lang.String" /> <column name="lastName" class="java.lang.String" /> </constructor-result> </sql-result-set-mapping> </entity-mappings>
VariousResultSelectTest.java
package org.arquillian.example; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.transaction.Transactional; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.persistence.UsingDataSet; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(Arquillian.class) public class VariousSelectTest { @Deployment public static Archive<?> createDeployment() { Archive<?> a = ShrinkWrap.create(WebArchive.class, "test.war") .addPackage(Employee.class.getPackage()) .addAsResource("test-persistence.xml", "META-INF/persistence.xml") .addAsResource("META-INF/orm.xml", "META-INF/orm.xml") .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") .addAsWebInfResource("jbossas-ds.xml"); return a; } @PersistenceContext EntityManager em; @Test @Transactional @UsingDataSet({"datasets/relativeSelect/dept.yml", "datasets/relativeSelect/employees.yml"}) public void select() throws Exception { dumpEntityList(em.createNamedQuery("findVarious").getResultList()); } protected void dumpEntityList(List<?> list){ for(Object o : list){ Object[] array = (Object[])o; Employee employee = (Employee) array[0]; Dept dept = (Dept) array[1]; EmployeeProfile employeeProfile = (EmployeeProfile) array[2]; System.out.println(""); System.out.println("---------------------------------"); System.out.printf("id=%d, firstName=%s, lastName=%s, dept_id=%s, deptName=%s, employee=%s, dept=%s\n", employee.getId(), employee.getFirstName(), employee.getLastName(), dept.getId(), dept.getDeptName(), em.contains(employee), em.contains(dept)); System.out.println(employeeProfile); System.out.println("---------------------------------"); } } }
実行結果
15:15:55,405 INFO [stdout] (pool-2-thread-20) Hibernate: SELECT emp.id, emp.firstName, emp.lastName, emp.dept_id, dep.deptName FROM Employee AS emp, Dept AS dep WHERE emp.dept_id = dep.id 15:15:55,409 INFO [stdout] (pool-2-thread-20) 15:15:55,409 INFO [stdout] (pool-2-thread-20) --------------------------------- 15:15:55,409 INFO [stdout] (pool-2-thread-20) id=-1, firstName=Taro, lastName=Yamada, dept_id=-1, deptName=Sales, employee=true, dept=true 15:15:55,409 INFO [stdout] (pool-2-thread-20) EmployeeProfile [deptName=Sales, firstName=Taro, lastName=Yamada] 15:15:55,410 INFO [stdout] (pool-2-thread-20) --------------------------------- 15:15:55,410 INFO [stdout] (pool-2-thread-20) 15:15:55,410 INFO [stdout] (pool-2-thread-20) --------------------------------- 15:15:55,410 INFO [stdout] (pool-2-thread-20) id=-2, firstName=Jiro, lastName=Suzuki, dept_id=-1, deptName=Sales, employee=true, dept=true 15:15:55,410 INFO [stdout] (pool-2-thread-20) EmployeeProfile [deptName=Sales, firstName=Jiro, lastName=Suzuki] 15:15:55,410 INFO [stdout] (pool-2-thread-20) --------------------------------- 15:15:55,410 INFO [stdout] (pool-2-thread-20) 15:15:55,410 INFO [stdout] (pool-2-thread-20) --------------------------------- 15:15:55,411 INFO [stdout] (pool-2-thread-20) id=-3, firstName=Saburo, lastName=Tanaka, dept_id=-2, deptName=Legal, employee=true, dept=true 15:15:55,411 INFO [stdout] (pool-2-thread-20) EmployeeProfile [deptName=Legal, firstName=Saburo, lastName=Tanaka] 15:15:55,411 INFO [stdout] (pool-2-thread-20) ---------------------------------
あんまり意味ないかもしれませんが柔軟に出来ているなぁと。
備考
今回使ったsql-result-set-mappingに、さらに以下を追加してもXML的には不正ではないのですが、
<column-result name="deptName"/>
動かそうとすると何故か以下のような例外が出て動きません。まああまり困ることもなさそうですが。
15:26:45,836 SEVERE [org.jboss.arquillian.protocol.jmx.JMXTestRunner] (pool-2-thread-21) Failed: org.arquillian.example.VariousSelectTest.select: javax.persistence.PersistenceException: org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [deptName] during auto-discovery of a native-sql query
参考文献
Tags: jpa
NativeQueryでconstructor-resultを使ってSELECTしてみる
TweetPosted on Sunday Jan 26, 2014 at 02:35PM in Technology
NativeQueryで複数のエンティティを1度にSELECTしてみるの続きです。JPA2.1のNativeQueryの新機能constructor-resultを使ってSELECTしてみます。
constructor-resultはJPQLのNEW句のようなものです。エンティティを拾ってくるクエリでなく、レポート的なのを出すクエリの場合とかに使うとキャストが要らなくなるので便利っぽいです。
環境
- Hibernate 4.3.0.Final
- WildFly8.0.0.CR1
- Oracle JDK7u51
- postgresql-9.3-1100.jdbc41.jar
- PostgreSQL 9.2.4
何をするか
エンティティと関連の構造は前回と同じです。
今回はDeptエンティティのdeptNameと、EmployeeのカウントをSELECTしてみます。
準備
配置図
図中で選択されている資源を作成または編集します。
- orm.xmlにNamedNativeQuery “findDeptNameAndEmployeeCount” とResultSetMapping “deptNameAndEmployeeCountResult” を追加します
- テストクラスConstructorResultSelectTestを作ります
- DTOクラスDeptNameAndEmployeeCountを作ります
- テストデータは前回のを流用します
DeptNameAndEmployeeCount.java
package org.arquillian.example; public class DeptNameAndEmployeeCount { private String deptName; private Number employeeCount; public DeptNameAndEmployeeCount(String deptName, Number employeeCount) { super(); this.deptName = deptName; this.employeeCount = employeeCount; } @Override public String toString() { return "DeptNameAndEmployeeCount [deptName=" + deptName + ", employeeCount=" + employeeCount + "]"; } }
orm.xml
<?xml version="1.0" encoding="UTF-8"?> <entity-mappings version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"> <named-native-query name="findDeptNameAndEmployeeCount" result-set-mapping="deptNameAndEmployeeCountResult"> <query><![CDATA[ SELECT dep.deptName, COUNT(dep.deptName) AS employeeCount FROM Dept AS dep, Employee AS emp WHERE dep.id = emp.dept_id GROUP BY dep.deptName ]]></query> </named-native-query> <sql-result-set-mapping name="deptNameAndEmployeeCountResult"> <constructor-result target-class="org.arquillian.example.DeptNameAndEmployeeCount"> <column name="deptName" class="java.lang.String" /> <column name="employeeCount" class="java.lang.Number" /> </constructor-result> </sql-result-set-mapping> </entity-mappings>
- column要素のclass属性は省略可みたい(少なくともHibernate4.3.1では動いた)
- ただcolumn要素自体は省略不可っぽい
ConstructorResultSelectTest.java
package org.arquillian.example; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.transaction.Transactional; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.persistence.UsingDataSet; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(Arquillian.class) public class ConstructorResultSelectTest { @Deployment public static Archive<?> createDeployment() { Archive<?> a = ShrinkWrap.create(WebArchive.class, "test.war") .addPackage(Employee.class.getPackage()) .addAsResource("test-persistence.xml", "META-INF/persistence.xml") .addAsResource("META-INF/orm.xml", "META-INF/orm.xml") .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") .addAsWebInfResource("jbossas-ds.xml"); return a; } @PersistenceContext EntityManager em; @Test @Transactional @UsingDataSet({"datasets/relativeSelect/dept.yml", "datasets/relativeSelect/employees.yml"}) public void select() throws Exception { dumpEntityList(em.createNamedQuery("findDeptNameAndEmployeeCount").getResultList()); } protected void dumpEntityList(List<?> list){ for(Object o : list){ System.out.println(o); } } }
実行結果
14:42:45,278 INFO [stdout] (pool-2-thread-17) Hibernate: SELECT dep.deptName, COUNT(dep.deptName) AS employeeCount FROM Dept AS dep, Employee AS emp WHERE dep.id = emp.dept_id GROUP BY dep.deptName 14:42:45,281 INFO [stdout] (pool-2-thread-17) DeptNameAndEmployeeCount [deptName=Legal, employeeCount=1] 14:42:45,282 INFO [stdout] (pool-2-thread-17) DeptNameAndEmployeeCount [deptName=Sales, employeeCount=2]
キャストが要らないのがいいですね。
続き
NativeQueryで複数のエンティティを同時にSELECTしつつconstructor-resultを使ってみる
参考文献
Tags: jpa
NativeQueryで複数のエンティティを1度にSELECTしてみる
TweetPosted on Sunday Jan 26, 2014 at 01:51PM in Technology
NativeQueryでエンティティとスカラ値を同時にSELECTしてみるの続きです。今回は2つのエンティティを1回のSELECT文で取得してみます。
環境
- Hibernate 4.3.0.Final
- WildFly8.0.0.CR1
- Oracle JDK7u51
- postgresql-9.3-1100.jdbc41.jar
- PostgreSQL 9.2.4
何をするか
エンティティと関連の構造は前回と同じです。
今回はEmployeeエンティティとDeptエンティティを同時にSELECTしてみます。
準備
配置図
図中で選択されている資源を作成または編集します。
- orm.xmlにNamedNativeQuery “findEmployeeWithDeptAtOnce” とResultSetMapping “employeeWithDeptResult” を追加します
- MultiEntitySelectTestを作ります
- テストデータは前回のを流用します
orm.xml
<?xml version="1.0" encoding="UTF-8"?> <entity-mappings version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"> <named-native-query name="findEmployeeWithDeptAtOnce" result-set-mapping="employeeWithDeptResult"> <query><![CDATA[ SELECT emp.id, emp.firstName, emp.lastName, emp.dept_id, dep.deptName FROM Employee AS emp, Dept AS dep WHERE emp.dept_id = dep.id ]]></query> </named-native-query> <sql-result-set-mapping name="employeeWithDeptResult"> <entity-result entity-class="org.arquillian.example.Employee"/> <entity-result entity-class="org.arquillian.example.Dept"> <field-result name="id" column="dept_id"/> <field-result name="deptName" column="deptName"/> </entity-result> </sql-result-set-mapping> </entity-mappings>
ResultSetMappingのfield-result要素で、Deptエンティティのidフィールドの値はクエリ中のdept_idだよ、と教えてやります
MultiEntitySelectTest.java
package org.arquillian.example; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.transaction.Transactional; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.persistence.UsingDataSet; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(Arquillian.class) public class MultiEntitySelectTest { @Deployment public static Archive<?> createDeployment() { Archive<?> a = ShrinkWrap.create(WebArchive.class, "test.war") .addPackage(Employee.class.getPackage()) .addAsResource("test-persistence.xml", "META-INF/persistence.xml") .addAsResource("META-INF/orm.xml", "META-INF/orm.xml") .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") .addAsWebInfResource("jbossas-ds.xml"); return a; } @PersistenceContext EntityManager em; @Test @Transactional @UsingDataSet({"datasets/relativeSelect/dept.yml", "datasets/relativeSelect/employees.yml"}) public void select() throws Exception { dumpEntityList(em.createNamedQuery("findEmployeeWithDeptAtOnce").getResultList()); } protected void dumpEntityList(List<?> list){ for(Object o : list){ Object[] array = (Object[])o; Employee employee = (Employee) array[0]; Dept dept = (Dept) array[1]; System.out.println(""); System.out.printf("id=%d, firstName=%s, lastName=%s, dept_id=%s, deptName=%s, employee=%s, dept=%s\n", employee.getId(), employee.getFirstName(), employee.getLastName(), dept.getId(), dept.getDeptName(), em.contains(employee), em.contains(dept)); System.out.println("---------------------------------"); System.out.println("checking relation references"); System.out.println(dept.getEmployees()); System.out.println(employee.getDept()); System.out.println("---------------------------------"); } } }
実行結果
4,688 INFO [stdout] (pool-2-thread-15) Hibernate: SELECT emp.id, emp.firstName, emp.lastName, emp.dept_id, dep.deptName FROM Employee AS emp, Dept AS dep WHERE emp.dept_id = dep.id 14:11:54,691 INFO [stdout] (pool-2-thread-15) 14:11:54,692 INFO [stdout] (pool-2-thread-15) id=-1, firstName=Taro, lastName=Yamada, dept_id=-1, deptName=Sales, employee=true, dept=true 14:11:54,692 INFO [stdout] (pool-2-thread-15) --------------------------------- 14:11:54,692 INFO [stdout] (pool-2-thread-15) checking relation references 14:11:54,693 INFO [stdout] (pool-2-thread-15) [Employee [id=-1, firstName=Taro, lastName=Yamada, dept=Dept [id=-1, deptName=Sales, employees=2]], Employee [id=-2, firstName=Jiro, lastName=Suzuki, dept=Dept [id=-1, deptName=Sales, employees=2]]] 14:11:54,693 INFO [stdout] (pool-2-thread-15) Dept [id=-1, deptName=Sales, employees=2] 14:11:54,693 INFO [stdout] (pool-2-thread-15) --------------------------------- 14:11:54,693 INFO [stdout] (pool-2-thread-15) 14:11:54,693 INFO [stdout] (pool-2-thread-15) id=-2, firstName=Jiro, lastName=Suzuki, dept_id=-1, deptName=Sales, employee=true, dept=true 14:11:54,694 INFO [stdout] (pool-2-thread-15) --------------------------------- 14:11:54,694 INFO [stdout] (pool-2-thread-15) checking relation references 14:11:54,694 INFO [stdout] (pool-2-thread-15) [Employee [id=-1, firstName=Taro, lastName=Yamada, dept=Dept [id=-1, deptName=Sales, employees=2]], Employee [id=-2, firstName=Jiro, lastName=Suzuki, dept=Dept [id=-1, deptName=Sales, employees=2]]] 14:11:54,694 INFO [stdout] (pool-2-thread-15) Dept [id=-1, deptName=Sales, employees=2] 14:11:54,694 INFO [stdout] (pool-2-thread-15) --------------------------------- 14:11:54,694 INFO [stdout] (pool-2-thread-15) 14:11:54,694 INFO [stdout] (pool-2-thread-15) id=-3, firstName=Saburo, lastName=Tanaka, dept_id=-2, deptName=Legal, employee=true, dept=true 14:11:54,695 INFO [stdout] (pool-2-thread-15) --------------------------------- 14:11:54,695 INFO [stdout] (pool-2-thread-15) checking relation references 14:11:54,695 INFO [stdout] (pool-2-thread-15) [Employee [id=-3, firstName=Saburo, lastName=Tanaka, dept=Dept [id=-2, deptName=Legal, employees=1]]] 14:11:54,696 INFO [stdout] (pool-2-thread-15) Dept [id=-2, deptName=Legal, employees=1] 14:11:54,696 INFO [stdout] (pool-2-thread-15) ---------------------------------
SELECT文が1回になったので状況によってはクエリを軽くするのに寄与するかもしれません。また、こういう取り方をしてもお互いの参照はちゃんと設定されていて、実際にアクセスしてもよけいなクエリを実行する事もないようです。賢い。
と思ったのだがorg.hibernate.SQLのログレベルを上げて見ると、別途SELECT文が実行されている気配。persistence.xmlにhibernate.show_sqlを設定しただけでは全てのSQLは出ないという事なのか、あるいは見落としたのか…。PostgreSQL側にSQLをログ出力させる設定を加えて見てみるとこんなのが出ている。
Feb 2 11:35:46 kyle-no-MacBook.local postgres[1120]: [877-1] 2014-02-02 11:35:46 JST LOG: execute <unnamed>: SELECT emp.id, emp.firstName, emp.lastName, emp.dept_id, dep.deptName FROM Employee AS emp, Dept AS dep WHERE emp.dept_id = dep.id Feb 2 11:35:46 kyle-no-MacBook.local postgres[1120]: [878-1] 2014-02-02 11:35:46 JST LOG: execute <unnamed>: select employees0_.dept_id as dept_id4_0_0_, employees0_.id as id1_1_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id4_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_ from Employee employees0_ where employees0_.dept_id=$1 Feb 2 11:35:46 kyle-no-MacBook.local postgres[1120]: [878-2] 2014-02-02 11:35:46 JST DETAIL: parameters: $1 = '-1' Feb 2 11:35:46 kyle-no-MacBook.local postgres[1120]: [879-1] 2014-02-02 11:35:46 JST LOG: execute <unnamed>: select employees0_.dept_id as dept_id4_0_0_, employees0_.id as id1_1_0_, employees0_.id as id1_1_1_, employees0_.dept_id as dept_id4_1_1_, employees0_.firstName as firstNam2_1_1_, employees0_.lastName as lastName3_1_1_ from Employee employees0_ where employees0_.dept_id=$1 Feb 2 11:35:46 kyle-no-MacBook.local postgres[1120]: [879-2] 2014-02-02 11:35:46 JST DETAIL: parameters: $1 = '-2'
続き
NativeQueryでconstructor-resultを使ってSELECTしてみる
参考文献
Tags: jpa