我正在尝试查询a person by id
,并且在我的架构中,我在@OneToMany
和Address
之间有一个Person
引用,并在{}之间引用了ManyToOne
个引用学校。我使用命名查询和查询提示来获得这个简单任务的最佳性能查询,但是查看堆栈跟踪(发布了相关部分),当我想要的只是id对象的人时,EclipseLink生成三个Select语句?使用渴望获取是杀死性能所以我的问题是我如何使用JPQL创建一个查询,通过ID获取单个人对象而不引用其他类?
@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;
}
堆栈跟踪:它搜索等于1的addressID
的最后一位是挂起
[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();
Student.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-");
}
}
答案 0 :(得分:1)
从以下几行:
2012-06-26 20:47:29,802 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - 处理bean'org.bixin.dugsi.domain.Student'的注入方法:暂时javax的PersistenceElement .persistence.EntityManager org.bixin.dugsi.domain.Person.entityManager
您似乎正在对实体类进行一些注入。需要确定实体的完整来源。然而,如果你这样做..好吧..不要:)在每个实体上创建弹簧代理或做DI是一种矫枉过正,也几乎肯定会打败整个懒惰的初始化,因为Spring会访问在执行DI时,ManyToOne集合也会触发这些实体的数据库负载。
作为旁注:您的实体不应包含业务逻辑,因此没有理由对它们进行任何依赖注入。
答案 1 :(得分:0)
将获取设置为LAZY访问Person不应该触发对地址或学校的查询。您是否启用了编织(使用代理或Java EE / Spring编织)?您可能需要启用动态编织或使用静态编织。
可能是触发关系的其他东西,您可以在EclipseLink会话查询执行中放置断点或转储堆栈跟踪(使用SessionEvent)。
您对地址的批量提取没有意义,批量提取适用于查询返回许多结果,但您通过id查找。您可以使用连接提取(在JPQL中或通过连接提取提示)。
我不确定它是如何挂起的,打破进程以获取堆栈跟踪以查看它正在等待的内容。