Entries tagged [jpa]
NativeQueryでエンティティとスカラ値を同時にSELECTしてみる
TweetPosted on Sunday Jan 26, 2014 at 01:06PM in Technology
NativeQueryで関連持ちエンティティをSELECTしてみるの続きです。今回はエンティティとCOUNT関数の結果を同時にSELECTしてみます。
環境
- Hibernate 4.3.0.Final
- WildFly8.0.0.CR1
- Oracle JDK7u51
- postgresql-9.3-1100.jdbc41.jar
- PostgreSQL 9.2.4
何をするか
エンティティと関連の構造は前回と同じです。
今回は部署エンティティと一緒に社員数のカウントを取ってみます。
準備
配置図

図中で選択されている資源を作成または編集します。
- orm.xmlにNamedNativeQuery “findDeptWithCount” とResultSetMapping “deptWithCountResult” を追加します
- EntityWithScalarSelectTestを作ります
- テストデータは前回のを流用します
資源
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="findEmployee" result-set-mapping="employeeResult">
<query><![CDATA[
SELECT
emp.id,
emp.firstName,
emp.lastName
FROM
Employee AS emp
]]></query>
</named-native-query>
<named-native-query name="findEmployeeWithDept" result-set-mapping="employeeResult">
<query><![CDATA[
SELECT
emp.id,
emp.firstName,
emp.lastName,
emp.dept_id
FROM
Employee AS emp
]]></query>
</named-native-query>
<named-native-query name="findDeptWithCount" result-set-mapping="deptWithCountResult">
<query><![CDATA[
SELECT
dep.id,
dep.deptName,
COUNT(dep.id) AS employeeCount
FROM
Dept AS dep,
Employee AS emp
WHERE
dep.id = emp.dept_id
GROUP BY
dep.id
]]></query>
</named-native-query>
<sql-result-set-mapping name="employeeResult">
<entity-result entity-class="org.arquillian.example.Employee"/>
</sql-result-set-mapping>
<sql-result-set-mapping name="deptWithCountResult">
<entity-result entity-class="org.arquillian.example.Dept"/>
<column-result name="employeeCount"/>
</sql-result-set-mapping>
</entity-mappings>
EntityWithScalarSelectTest.java
この環境だとCOUNT()の結果はBigIntegerになるようですが、別の環境ではLongだったりいろいろかもしれません
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 EntityWithScalarSelectTest {
@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("findDeptWithCount").getResultList());
}
protected void dumpEntityList(List<?> list){
for(Object o : list){
Object[] array = (Object[])o;
Dept dept = (Dept) array[0];
Number employees = (Number) array[1];
System.out.printf("id=%d, deptName=%s, employees=%s, contains=%s\n",
dept.getId(), dept.getDeptName(), employees, em.contains(dept));
}
}
}
実行結果
13:05:40,545 INFO [stdout] (pool-2-thread-9) Hibernate: SELECT dep.id, dep.deptName, COUNT(dep.id) AS employeeCount FROM Dept AS dep, Employee AS emp WHERE dep.id = emp.dept_id GROUP BY dep.id 13:05:40,548 INFO [stdout] (pool-2-thread-9) id=-1, deptName=Sales, employees=2, contains=true 13:05:40,548 INFO [stdout] (pool-2-thread-9) id=-2, deptName=Legal, employees=1, contains=true
この取り方でもちゃんとmanagedで返ってきているのがすごい。
続き
NativeQueryで複数のエンティティを1度にSELECTしてみる
参考文献
Tags: jpa
NativeQueryで関連持ちエンティティをSELECTしてみる
TweetPosted on Sunday Jan 26, 2014 at 11:05AM in Technology
NativeQueryでSELECTしてみるの続きです。前回は関連の無いエンティティでしたが今回は関連のあるエンティティをSELECTしてみます
環境
- Hibernate 4.3.0.Final
- WildFly8.0.0.CR1
- Oracle JDK7u51
- postgresql-9.3-1100.jdbc41.jar
- PostgreSQL 9.2.4
用意するエンティティ
Deptエンティティを追加してこういう感じにします。
Hibernateが作るテーブルはこういう感じになります
jpaprac=# \d dept
Table "public.dept"
Column | Type | Modifiers
----------+------------------------+-----------
id | bigint | not null
deptname | character varying(255) |
Indexes:
"dept_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "employee" CONSTRAINT "fk_1n3sqh4h9gtmwb1o1twpoi30l" FOREIGN KEY (dept_id) REFERENCES dept(id)
jpaprac=# \d employee
Table "public.employee"
Column | Type | Modifiers
-----------+------------------------+-----------
id | bigint | not null
firstname | character varying(255) |
lastname | character varying(255) |
dept_id | bigint |
Indexes:
"employee_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"fk_1n3sqh4h9gtmwb1o1twpoi30l" FOREIGN KEY (dept_id) REFERENCES dept(id)
jpaprac=#
準備
配置図

図中で選択されている資源を作成または編集します。Employee.javaは前回も使いましたが関連を追加するために若干変更します。orm.xmlには新たなクエリを追加します。
Dept.java
package org.arquillian.example;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Dept implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String deptName;
@OneToMany(mappedBy = "dept")
private List<Employee> employees;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
@Override
public String toString() {
return "Dept [id=" + id + ", deptName=" + deptName + ", employees=" + employees.size() + "]";
}
}
Employee.java
package org.arquillian.example;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Entity
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String firstName;
@Column
private String lastName;
@ManyToOne
@JoinColumn
private Dept dept;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", dept=" + dept + "]";
}
}
orm.xml
findEmployeeWithDeptを追加します
<?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="findEmployee" result-set-mapping="employeeResult">
<query><![CDATA[
SELECT
emp.id,
emp.firstName,
emp.lastName
FROM
Employee AS emp
]]></query>
</named-native-query>
<named-native-query name="findEmployeeWithDept" result-set-mapping="employeeResult">
<query><![CDATA[
SELECT
emp.id,
emp.firstName,
emp.lastName,
emp.dept_id
FROM
Employee AS emp
]]></query>
</named-native-query>
<sql-result-set-mapping name="employeeResult">
<entity-result entity-class="org.arquillian.example.Employee"/>
</sql-result-set-mapping>
</entity-mappings>
RelativeSelectTest.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 RelativeSelectTest {
@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("findEmployeeWithDept", Employee.class).getResultList());
}
protected void dumpEntityList(List<Employee> employees){
for(Employee e : employees){
String fmt = String.format("id=%s, firstName=%s, lastName=%s, deptName=%s",
e.getId(), e.getFirstName(), e.getLastName(), e.getDept().getDeptName());
System.out.println(fmt);
}
}
}
dept.yml
dept:
- id: -1
deptName: Sales
- id: -2
deptName: Legal
employees.yml
employee:
- id: -1
firstname: Taro
lastname: Yamada
dept_id: -1
- id: -2
firstname: Jiro
lastname: Suzuki
dept_id: -1
- id: -3
firstname: Saburo
lastname: Tanaka
dept_id: -2
実行結果
11:48:22,373 INFO [stdout] (pool-2-thread-4) Hibernate: SELECT emp.id, emp.firstName, emp.lastName, emp.dept_id FROM Employee AS emp 11:48:22,375 INFO [stdout] (pool-2-thread-4) Hibernate: select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 11:48:22,376 INFO [stdout] (pool-2-thread-4) Hibernate: select dept0_.id as id1_0_0_, dept0_.deptName as deptName2_0_0_ from Dept dept0_ where dept0_.id=? 11:48:22,377 INFO [stdout] (pool-2-thread-4) id=-1, firstName=Taro, lastName=Yamada, deptName=Sales 11:48:22,377 INFO [stdout] (pool-2-thread-4) id=-2, firstName=Jiro, lastName=Suzuki, deptName=Sales 11:48:22,377 INFO [stdout] (pool-2-thread-4) id=-3, firstName=Saburo, lastName=Tanaka, deptName=Legal
備考
NativeQueryではEmployeeテーブルのデータしか取ってきていないのですが、親レコードへの参照であるdept_idを拾ってきていれば、DeptテーブルのデータはJPA側で勝手に別途SELECT文を発行して取ってきてくれるようですね。
続き
NativeQueryでエンティティとスカラ値を同時にSELECTしてみる
参考文献
Tags: jpa
NativeQueryでSELECTしてみる
TweetPosted on Saturday Jan 25, 2014 at 11:37PM in Technology
ここではNativeQueryを使うまでもない簡単な単独のエンティティをSELECTしてみます。複雑なのは後々。
環境
- Hibernate 4.3.0.Final
- WildFly8.0.0.CR1
- Oracle JDK7u51
- postgresql-9.3-1100.jdbc41.jar
- PostgreSQL 9.2.4
前提条件
- Arquillian Persistence ExtensionとJavaEE7を使います
- プロジェクトを作ったりする作業はJavaEE7プロジェクトでArquillianを使ってみるあたりを参照
- WildFlyへのJDBCドライバ配備方法等はWildFly - CLIでデータソースを定義するあたりを参照
関連を持たない単独のエンティティをSELECTしてみる
エンティティクラス等を配置
配置図
図で選択されている資源を作る必要が有ります

Employee.java
package org.arquillian.example;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String firstName;
@Column
private String lastName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Employee [id=" + id + ", 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="findEmployee" result-set-mapping="employeeResult">
<query><![CDATA[
SELECT
emp.id,
emp.firstName,
emp.lastName
FROM
Employee AS emp
]]></query>
</named-native-query>
<sql-result-set-mapping name="employeeResult">
<entity-result entity-class="org.arquillian.example.Employee"/>
</sql-result-set-mapping>
</entity-mappings>
IndependentSelectTest.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 IndependentSelectTest {
@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/independentSelect/employees.yml")
public void select() throws Exception {
dumpEntityList(em.createNamedQuery("findEmployee", Employee.class).getResultList());
}
protected void dumpEntityList(List<?> list){
for(Object o : list){
System.out.println(o + ", contains=" + em.contains(o));
}
}
}
employees.yml
employee:
- id: -1
firstname: Taro
lastname: Yamada
- id: -2
firstname: Jiro
lastname: Suzuki
- id: -3
firstname: Saburo
lastname: Tanaka
jbossas-ds.xml
ローカルで動いているPostgreSQLにjpapracというDBを作っておきます
<?xml version="1.0" encoding="UTF-8"?>
<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.jboss.org/ironjacamar/schema
http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
<datasource enabled="true" jndi-name="jdbc/arquillian" pool-name="ArquillianPostgresPool">
<connection-url>jdbc:postgresql://localhost:5432/jpaprac</connection-url>
<driver>postgresql-9.3-1100.jdbc41.jar</driver>
<security>
<user-name>postgres</user-name>
<password>***</password>
</security>
</datasource>
</datasources>
test-persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="test">
<jta-data-source>jdbc/arquillian</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
実行結果
コンソールの出力を関係ありそうなところだけ抜粋
10:23:35,245 INFO [stdout] (pool-2-thread-12) Hibernate: SELECT emp.id, emp.firstName, emp.lastName FROM Employee AS emp 10:23:35,248 INFO [stdout] (pool-2-thread-12) Employee [id=-1, firstName=Taro, lastName=Yamada], contains=true 10:23:35,248 INFO [stdout] (pool-2-thread-12) Employee [id=-2, firstName=Jiro, lastName=Suzuki], contains=true 10:23:35,248 INFO [stdout] (pool-2-thread-12) Employee [id=-3, firstName=Saburo, lastName=Tanaka], contains=true
普通に出てますね。NamedNativeQueryにしてResultSetMappingまで定義するとManagedになる。
備考
@UsingDataSetアノテーションをテストメソッドに付けると、Arquillian Persistence Extensionがデータ投入してくれますが、投入したデータはテスト後にTRUNCATEされてしまうので、テスト後にテーブルで確認しようとしても見えないようです[3]。これを抑制する設定は現状存在しないらしい。まあデバッガか何かで止めれば見られるだろうけど。
arquillian.xmlにこういう内容を書けばTRUNCATEがテスト実行前に走るようになるので、テスト実行後のデータを簡単に確認できます
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="persistence">
<property name="defaultCleanupPhase">BEFORE</property>
</extension>
</arquillian>
HibernateのSQLログは、persistence.xmlのproperties要素内に以下のようなのを追記すると複数行使って見やすくインデントとかしてくれる
<property name="hibernate.format_sql" value="true"/>
続き
NativeQueryで関連持ちエンティティをSELECTしてみる
参考文献
Tags: jpa
JPQLをorm.xmlに書いてみる
TweetPosted on Tuesday Jan 21, 2014 at 08:04AM in Technology
何をするの?
JPQLをorm.xmlに書いて動かしてみます。
環境
- WildFly8.0.0CR1
- Eclipse Kepler SR1
- PostgreSQL 9.2.4
- Oracle JDK7u51
準備
これの続きです。
orm.xmlに書いたクエリを動かしてみる
orm.xmlを作る
src/main/java/META-INFの下に作ります。右クリックメニューからNew→JPA ORM Mapping File
場所を確かめてFinish
出来たら開きましょう
クエリを書く
named-queryを書いてみます。エンティティに直書きしてたのとほとんど同じです。違うのはidで逆順ソートかけてるとこだけです
<?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-query name="findHogeEntityAllDesc">
<query>
SELECT
e
FROM
HogeEntity e
ORDER BY
e.id DESC
</query>
</named-query>
</entity-mappings>
この書き方だと < とか > をエスケープしないといけないのが面倒くさいですが、こういう感じで書くとそのまま書けます。
Daoにメソッドを追加
findAllDesc()を追加します
package com.example.dao;
import java.util.Date;
import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import com.example.entity.HogeEntity;
@Named
public class HogeEntityDao {
@PersistenceContext
private EntityManager em;
@Transactional
public void save() {
HogeEntity e = new HogeEntity();
e.setHogeDate(new Date());
em.persist(e);
}
public List<HogeEntity> findAll() {
return em.createNamedQuery("findHogeEntityAll", HogeEntity.class).getResultList();
}
public List<HogeEntity> findAllDesc() {
return em.createNamedQuery("findHogeEntityAllDesc", HogeEntity.class).getResultList();
}
}
サーブレットから呼び出すメソッドを変更
package com.example.servlet;
import java.io.IOException;
import java.io.Writer;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.example.dao.HogeEntityDao;
import com.example.entity.HogeEntity;
@WebServlet("/HogeServlet")
public class HogeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Inject
HogeEntityDao dao;
public HogeServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
dao.save();
try (Writer w = response.getWriter()) {
// for (HogeEntity e : dao.findAll()) {
for (HogeEntity e : dao.findAllDesc()) {
w.write("id=" + e.getId() + ", hogeDate=" + e.getHogeDate() + "\n");
}
}
}
}
動かしてみる
逆順になりました。改行とかも自由なので、やっぱりクエリはエンティティのアノテーション内に書くよりorm.xmlに書いた方が良い気がします。
Tags: jpa
動かしてみる
TweetPosted on Tuesday Jan 21, 2014 at 07:57AM in Technology
何をするの?
開発環境を設定して、JPAを叩くCDI管理Beanと、それを叩くサーブレットを作って動かしてみます。
環境
- WildFly8.0.0CR1
- Eclipse Kepler SR1
- PostgreSQL 9.2.4
- Oracle JDK7u51
準備
プロジェクトを作る
- まずこの要領で空っぽのプロジェクトjpahelloを作ります
-
Project Facetsを開き、CDIとJPAにチェックを入れてOKを押します
-
何故かbeans.xmlが出来ないので作ります。web-resourcesを右クリックしてNew→File beans.xmlを選択
-
フォルダを「jpahello/src/main/webapp/WEB-INF」にしてFinish
-
persistence.xmlとbeans.xmlができた事を確認します。
データベース作成とデータソース定義
このへんを参考にすると良いかも
persistence.xmlの設定をする
Persistence provider
先ほど作ったpersistence.xmlをダブルクリックして開いてみましょう
Persistence providerを設定します。WildFlyにはHibernateが入っているので
org.hibernate.ejb.HibernatePersistenceになります。
Connection
次はデータソースの設定です。画面下部のConnectionタブを押して画面を切り替えます
JTA data sourceにAPサーバに登録してあるデータソースのJNDI名を入力します
Schema Generation
次はDDL自動生成の設定です。画面下部のSchema Generationタブを押して画面を切り替えます
Database actionをDrop and createにしておきます。こうするとデプロイの度にDROPとCREATEが走ります。ちょっといじりたいだけなのでこれで。
Sourceを確認
画面下部のSourceタブを押して画面を切り替えるとpersistence.xmlが確認出来ます。こんな感じになってるのを確認したら保存しましょう。
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="jpahello"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:jboss/jdbc/TestDS</jta-data-source> <properties> <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/> </properties> </persistence-unit> </persistence>
エンティティを作る
-
src/main/javaで右クリック→New→JPA Entityを選択
-
Java packageとClass nameを埋めてFinish
-
内容はこんな感じで
package com.example.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
@NamedQueries({ @NamedQuery(name = "findHogeEntityAll", query = "SELECT e FROM HogeEntity e") })
public class HogeEntity implements Serializable {
private static final long serialVersionUID = 1L;
public HogeEntity() {
super();
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false)
private Long id;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date hogeDate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getHogeDate() {
return hogeDate;
}
public void setHogeDate(Date hogeDate) {
this.hogeDate = hogeDate;
}
}
Dao的なクラスを作る
package com.example.dao;
import java.util.Date;
import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import com.example.entity.HogeEntity;
@Named
public class HogeEntityDao {
@PersistenceContext
private EntityManager em;
@Transactional
public void save() {
HogeEntity e = new HogeEntity();
e.setHogeDate(new Date());
em.persist(e);
}
public List<HogeEntity> findAll() {
return em.createNamedQuery("findHogeEntityAll", HogeEntity.class).getResultList();
}
}
サーブレットを作る
package com.example.servlet;
import java.io.IOException;
import java.io.Writer;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.example.dao.HogeEntityDao;
import com.example.entity.HogeEntity;
@WebServlet("/HogeServlet")
public class HogeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Inject
HogeEntityDao dao;
public HogeServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
dao.save();
try (Writer w = response.getWriter()) {
for (HogeEntity e : dao.findAll()) {
w.write("id=" + e.getId() + ", hogeDate=" + e.getHogeDate() + "\n");
}
}
}
}
作った資源を確認
5つ全部あるか確認しましょう。
デプロイしてみる
コンソールにこんなのが流れるはず
17:05:24,199 INFO [org.jboss.as.server.deployment] (MSC service thread 1-14) JBAS015876: Starting deployment of "jpahello.war" (runtime-name: "jpahello.war") 17:05:24,219 INFO [org.jboss.as.jpa] (MSC service thread 1-3) JBAS011401: Read persistence.xml for jpahello 17:05:24,227 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 264) JBAS011409: Starting Persistence Unit (phase 1 of 2) Service 'jpahello.war#jpahello' 17:05:24,227 INFO [org.hibernate.jpa.internal.util.LogHelper] (ServerService Thread Pool -- 264) HHH000204: Processing PersistenceUnitInfo [ name: jpahello ...] 17:05:24,236 INFO [org.jboss.weld.deployer] (MSC service thread 1-15) JBAS016002: Processing weld deployment jpahello.war 17:05:24,247 INFO [org.jboss.weld.deployer] (MSC service thread 1-9) JBAS016005: Starting Services for CDI deployment: jpahello.war 17:05:24,249 INFO [org.jboss.weld.deployer] (MSC service thread 1-16) JBAS016008: Starting weld service for deployment jpahello.war 17:05:24,252 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 264) JBAS011409: Starting Persistence Unit (phase 2 of 2) Service 'jpahello.war#jpahello' 17:05:24,425 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 264) HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL9Dialect 17:05:24,426 INFO [org.hibernate.engine.jdbc.internal.LobCreatorBuilder] (ServerService Thread Pool -- 264) HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException 17:05:24,428 INFO [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (ServerService Thread Pool -- 264) HHH000397: Using ASTQueryTranslatorFactory 17:05:24,437 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 264) HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL9Dialect 17:05:24,443 WARN [org.hibernate.jpa.internal.schemagen.GenerationTargetToDatabase] (ServerService Thread Pool -- 264) Unable to execute JPA schema generation drop command [drop table HogeEntity cascade] 17:05:24,443 WARN [org.hibernate.jpa.internal.schemagen.GenerationTargetToDatabase] (ServerService Thread Pool -- 264) Unable to execute JPA schema generation drop command [drop sequence hibernate_sequence] 17:05:24,663 INFO [org.wildfly.extension.undertow] (MSC service thread 1-8) JBAS017534: Register web context: /jpahello 17:05:24,671 INFO [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "jpahello.war" (runtime-name : "jpahello.war")
DBはどうなっているかというと
testdb=# \d
List of relations
Schema | Name | Type | Owner
--------+--------------------+----------+----------
public | hibernate_sequence | sequence | postgres
public | hogeentity | table | postgres
(2 rows)
testdb=# \d hogeentity
Table "public.hogeentity"
Column | Type | Modifiers
----------+-----------------------------+-----------
id | bigint | not null
hogedate | timestamp without time zone |
Indexes:
"hogeentity_pkey" PRIMARY KEY, btree (id)
testdb=# \d hibernate_sequence
Sequence "public.hibernate_sequence"
Column | Type | Value
---------------+---------+---------------------
sequence_name | name | hibernate_sequence
last_value | bigint | 1
start_value | bigint | 1
increment_by | bigint | 1
max_value | bigint | 9223372036854775807
min_value | bigint | 1
cache_value | bigint | 1
log_cnt | bigint | 0
is_cycled | boolean | f
is_called | boolean | f
testdb=#
自動で作ってくれると楽ですね
アクセスしてみる
リロードするたびに増えていきます。
テーブルも見てみましょう
testdb=# select * from hogeentity ; id | hogedate ----+------------------------- 1 | 2014-01-20 17:09:57.694 2 | 2014-01-20 17:09:58.091 3 | 2014-01-20 17:09:59.28 4 | 2014-01-20 17:09:59.475 5 | 2014-01-20 17:09:59.629 6 | 2014-01-20 17:09:59.812 7 | 2014-01-20 17:09:59.966 8 | 2014-01-20 17:10:03.878 (8 rows) testdb=#
ちゃんと動いているようですね
参考文献
Tags: jpa