1

私はクエリを実行しようとa person by idしていますが、以下の私のスキーマでは、と の@OneToMany間の参照Addressと、 person と School の間の参照があります。名前付きクエリとクエリ ヒントを使用して、この単純なタスクに最適なパフォーマンスのクエリを取得しますが、スタック トレース (投稿された関連部分) を見ると、id による個人オブジェクトだけが必要な場合、EclipseLink は 3 つの Select ステートメントを生成しますか? 熱心なフェッチを使用するとパフォーマンスが低下するため、他のクラスを参照せずにIDで単一の個人オブジェクトを取得するJPQLを使用してクエリを作成するにはどうすればよいですか?PersonManyToOne

@NamedQuery(
        name="findPersonById",
        query="SELECT p FROM Person as p  WHERE p.id = :id",
                hints={@QueryHint(name="eclipselink.batch.type", value="JOIN"),
                @QueryHint(name="eclipselink.batch", value="p.address")
                }
)
public class Person {

    @Id
    @TableGenerator(name = "TABLE_GEN", table = "PERSON_SEQUENCE_TABLE", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PER_SEQ", allocationSize = 1, initialValue = 10000)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
    @Column(name = "personID")
    private Long id;

    @ManyToOne(cascade = CascadeType.PERSIST,fetch = FetchType.LAZY)
    @JoinColumn(name = "addressID")
    private Address address;

    @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
    @JoinColumn(name = "schoolID")
    private School school;

}

住所エンティティ

public class Address {


    @Id
    @TableGenerator(name = "ADDRESS_TABLE_GEN", table = "ADDRESS_SEQUENCE_TABLE", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "ADDR_SEQ", allocationSize = 1, initialValue = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "ADDRESS_TABLE_GEN")
    @Column(name = "addressID")
    private Long id;


    @OneToMany(cascade = CascadeType.ALL, mappedBy = "address")
    private Set<Person> persons = new HashSet<Person>();

名前付きクエリの実装

public Person getPersonQueryBatch(Long id){

    EntityManager entityManager = factory.createEntityManager();
    Person person = null;

    try {

         List<Person> results = entityManager.createNamedQuery("findPersonById")
        .setParameter("id", id)
        .getResultList();
        if(!results.isEmpty()){
            // ignores multiple results
            person = results.get(0);
        }
    } catch (NoResultException e) {
        e.printStackTrace();
    }

    entityManager.close();
    return person;

}

addressIDスタック トレース: 1 に等しいan を検索する最後のビットがハングしている

[EL Finest]: jpa: 2012-06-26 20:47:29.78--ServerSession(1259621282)--Thread(Thread[main,5,main])--Begin deploying Persistence Unit persistenceUnit; session file:/Users/warz07/Documents/workspace-sts-2.8.0.RELEASE/dugsimanager/target/classes/_persistenceUnit; state Deployed; factoryCount 2
[EL Finest]: jpa: 2012-06-26 20:47:29.781--ServerSession(1259621282)--Thread(Thread[main,5,main])--End deploying Persistence Unit persistenceUnit; session file:/Users/warz07/Documents/workspace-sts-2.8.0.RELEASE/dugsimanager/target/classes/_persistenceUnit; state Deployed; factoryCount 2
[EL Finer]: connection: 2012-06-26 20:47:29.787--ServerSession(1259621282)--Thread(Thread[main,5,main])--client acquired: 67158058
[EL Finer]: transaction: 2012-06-26 20:47:29.788--ClientSession(67158058)--Thread(Thread[main,5,main])--acquire unit of work: 1296566131
[EL Finest]: query: 2012-06-26 20:47:29.788--UnitOfWork(1296566131)--Thread(Thread[main,5,main])--Execute query ReadObjectQuery(name="findPersonById" referenceClass=Person sql="SELECT personID, TYPE, DATEADDED, FIRSTNAME, LASTNAME, MIDDLENAME, ACTIVE, BIRTHDAY, EMAILADDRESS, GENDER, IMAGEPATH, MARITAL, PRIMARYTELEPHONE, SECONDARYTELEPHONE, version, addressID, schoolID, ETHNICITY, HISPANIC, MAJOR, NATIVELANGUAGE, RELIGIOUSAFFILIATION, studentId FROM PERSON WHERE (personID = ?)")
[EL Finest]: connection: 2012-06-26 20:47:29.789--ServerSession(1259621282)--Connection(65769329)--Thread(Thread[main,5,main])--Connection acquired from connection pool [read].
[EL Finest]: connection: 2012-06-26 20:47:29.789--ServerSession(1259621282)--Thread(Thread[main,5,main])--reconnecting to external connection pool
[EL Fine]: sql: 2012-06-26 20:47:29.79--ServerSession(1259621282)--Connection(1578517945)--Thread(Thread[main,5,main])--SELECT personID, TYPE, DATEADDED, FIRSTNAME, LASTNAME, MIDDLENAME, ACTIVE, BIRTHDAY, EMAILADDRESS, GENDER, IMAGEPATH, MARITAL, PRIMARYTELEPHONE, SECONDARYTELEPHONE, version, addressID, schoolID, ETHNICITY, HISPANIC, MAJOR, NATIVELANGUAGE, RELIGIOUSAFFILIATION, studentId FROM PERSON WHERE (personID = ?)
    bind => [10000]
[EL Finest]: connection: 2012-06-26 20:47:29.798--ServerSession(1259621282)--Connection(65769329)--Thread(Thread[main,5,main])--Connection released to connection pool [read].
2012-06-26 20:47:29,802 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'org.bixin.dugsi.domain.Student': PersistenceElement for transient javax.persistence.EntityManager org.bixin.dugsi.domain.Person.entityManager
2012-06-26 20:47:29,803 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'entityManagerFactory'
[EL Finest]: query: 2012-06-26 20:47:29.821--ServerSession(1259621282)--Thread(Thread[main,5,main])--Execute query ReadAllQuery(name="address" referenceClass=Address sql="SELECT DISTINCT t0.addressID, t0.CITY, t0.COUNTRY, t0.STATE_US, t0.STREETADDRESS, t0.STREETADDRESS2, t0.version, t0.ZIPCODE FROM ADDRESS t0, PERSON t1 WHERE ((t0.addressID = t1.addressID) AND (t1.personID = ?))")
[EL Finest]: connection: 2012-06-26 20:47:29.821--ServerSession(1259621282)--Connection(420965983)--Thread(Thread[main,5,main])--Connection acquired from connection pool [read].
[EL Finest]: connection: 2012-06-26 20:47:29.821--ServerSession(1259621282)--Thread(Thread[main,5,main])--reconnecting to external connection pool
[EL Fine]: sql: 2012-06-26 20:47:29.822--ServerSession(1259621282)--Connection(1364143063)--Thread(Thread[main,5,main])--SELECT DISTINCT t0.addressID, t0.CITY, t0.COUNTRY, t0.STATE_US, t0.STREETADDRESS, t0.STREETADDRESS2, t0.version, t0.ZIPCODE FROM ADDRESS t0, PERSON t1 WHERE ((t0.addressID = t1.addressID) AND (t1.personID = ?))
    bind => [10000]
[EL Finest]: connection: 2012-06-26 20:47:29.825--ServerSession(1259621282)--Connection(420965983)--Thread(Thread[main,5,main])--Connection released to connection pool [read].
2012-06-26 20:47:29,826 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'org.bixin.dugsi.domain.Address': PersistenceElement for transient javax.persistence.EntityManager org.bixin.dugsi.domain.Address.entityManager
2012-06-26 20:47:29,827 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'entityManagerFactory'
2012-06-26 20:47:29,830 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'org.bixin.dugsi.domain.Student': PersistenceElement for transient javax.persistence.EntityManager org.bixin.dugsi.domain.Person.entityManager
2012-06-26 20:47:29,831 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'entityManagerFactory'
[EL Finest]: transaction: 2012-06-26 20:47:29.832--UnitOfWork(1296566131)--Thread(Thread[main,5,main])--[EL Finest]: query: 2012-06-26 20:47:29.844--ServerSession(1259621282)--Thread(Thread[main,5,main])--Execute query ReadAllQuery(name="persons" referenceClass=Person )
[EL Finest]: connection: 2012-06-26 20:47:29.845--ServerSession(1259621282)--Connection(36219749)--Thread(Thread[main,5,main])--Connection acquired from connection pool [read].
[EL Finest]: connection: 2012-06-26 20:47:29.845--ServerSession(1259621282)--Thread(Thread[main,5,main])--reconnecting to external connection pool
[EL Fine]: sql: 2012-06-26 20:47:29.845--ServerSession(1259621282)--Connection(1007449342)--Thread(Thread[main,5,main])--SELECT personID, TYPE, DATEADDED, FIRSTNAME, LASTNAME, MIDDLENAME, ACTIVE, BIRTHDAY, EMAILADDRESS, GENDER, IMAGEPATH, MARITAL, PRIMARYTELEPHONE, SECONDARYTELEPHONE, version, addressID, schoolID, ETHNICITY, HISPANIC, MAJOR, NATIVELANGUAGE, RELIGIOUSAFFILIATION, studentId FROM PERSON WHERE (addressID = ?)
    bind => [1] 

クエリを実行するテスト ケース

public void testSavingPersonSchool(){

        PersonService personService = new PersonService();
        System.out.println("here\n");
        Person cPerson = personService.getPersonQueryBatch(Long.valueOf("10000"));
        System.out.println("not here\n");
        School school = new School();
        Address address = new Address();
        address.setStreetAddress("eer street");
        address.setCity("hiokins");
        address.setZipCode("34343");
        address.setState_us("MN");
        address.setCountry("usa");

        school.setName("Maui");
        school.setDescription("Thinking of dropping a summer class?");
        school.setAddress(address);
        school.setPrimaryPhone("3242342342");
        school.setAdmissionsPhone("3242342342");
        school.setAdmissionsEmailAddress("ads@d.com");
        school.setActive(true);
        cPerson.setSchool(school);
        school.persist();

学生.java

package org.bixin.dugsi.domain;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.OneToMany;
import javax.persistence.PostPersist;
import javax.validation.constraints.NotNull;
import org.eclipse.persistence.annotations.BatchFetch;
import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.annotations.JoinFetch;
import org.eclipse.persistence.annotations.JoinFetchType;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;
import org.springframework.roo.addon.tostring.RooToString;

@RooJavaBean
@RooToString
@RooJpaActiveRecord
@DiscriminatorValue("S")
public class Student extends Person {

    @Basic
    @Column(name = "studentId")
    private String studentIdentifier;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "student", fetch = FetchType.LAZY)
    private Set<Registration> registrations = new HashSet<Registration>();

    @PostPersist
    public void generateCode() {
        studentIdentifier = ("S-000-");
    }
}
4

2 に答える 2

1

これらの行から:

2012-06-26 20:47:29,802 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Bean 'org.bixin.dugsi.domain.Student' の注入されたメソッドの処理: 一時的な javax.persistence の PersistenceElement。 EntityManager org.bixin.dugsi.domain.Person.entityManager

エンティティクラスにインジェクションを行っているようです。ただし、エンティティの完全なソースを確認する必要があります。それにもかかわらず、それを行う場合..そうしないでください:)Springプロキシを作成したり、すべてのエンティティでDIを実行したりするのはやり過ぎであり、SpringはDIを実行中にManyToOneコレクションにアクセスするため、遅延初期化全体をほぼ確実に無効にします。これらのエンティティのデータベース負荷もトリガーします。

補足として、エンティティにはビジネス ロジックを含めないでください。したがって、エンティティに依存性注入を行う理由はありません。

于 2012-06-27T02:35:24.480 に答える
0

fetch を LAZY に設定すると、Person へのアクセスによって住所や学校へのクエリがトリガーされません。ウィービングを有効にしていますか (エージェントまたは Java EE/Spring ウィービングを使用)? 動的ウィービングを有効にするか、静的ウィービングを使用する必要がある場合があります。

他の何かが関係をトリガーしている可能性があります。ブレークポイントを設定するか、EclipseLink セッション クエリの実行で (SessionEvent を使用して) スタック トレースをダンプすることができます。

アドレスでのバッチ フェッチは意味がありません。バッチ フェッチは、クエリが多くの結果を返す場合に使用しますが、ID で検索しています。結合フェッチを使用できます (JPQL または結合フェッチ ヒントを介して)。

これがどのようにハングするかはわかりません。プロセスを中断してスタック トレースを取得し、何が待機しているかを確認してください。

于 2012-06-27T12:56:47.753 に答える