Kohei Nozaki's blog 

NativeQueryでSELECTしてみる


Posted 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

前提条件

関連を持たない単独のエンティティを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してみる

参考文献

  1. Hibernate - orm.xml - night, night, plane, plane, utf-8, utf-8
  2. Single Table ResultSet Mapping : ResultSet Mapping « JPA « Java Tutorial
  3. Table truncate after @UsingDataSet | Community
  4. Pro JPA 2



No one has commented yet.

Leave a Comment

HTML Syntax: NOT allowed