Использование критериев для запроса встраиваемого объекта

Я использую Toplink Grid (Eclipselink) в качестве основы реализации JPA.

Я встретил исключение, как показано ниже, когда пытался использовать критерии для запроса встраиваемого объекта:

 Exception [EclipseLink-6119] (Eclipse Persistence Services - 2.1.2.v20101206-r8635): org.eclipse.persistence.exceptions.QueryException
Exception Description: The join expression 
Query Key conInfo
   Base domain.de1003.Employee is not valid, or for a mapping type that does not support joining.
Query: ReportQuery(referenceClass=Employee )
    at org.eclipse.persistence.exceptions.QueryException.mappingForExpressionDoesNotSupportJoining(QueryException.java:659)
    at org.eclipse.persistence.internal.queries.JoinedAttributeManager.prepareJoinExpression(JoinedAttributeManager.java:851)
    at org.eclipse.persistence.internal.queries.JoinedAttributeManager.prepareJoinExpressions(JoinedAttributeManager.java:778)
    at org.eclipse.persistence.internal.queries.ReportItem.initialize(ReportItem.java:171)
    at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1035)
    at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:509)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:822)
    at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:470)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:710)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1038)
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:381)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1124)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2917)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1291)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1273)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1247)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:479)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getResultList(EJBQueryImpl.java:714)

И код, который я пробовал, выглядит следующим образом:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<ContactInfo> cq = cb.createQuery(ContactInfo.class);
Root<Employee> root = cq.from(Employee.class);
cq.select(root.<ContactInfo> get("conInfo"));
cq.where(cb.le(root.<Long> get("employId"), 3));

TypedQuery<ContactInfo> q = em.createQuery(cq);
List<ContactInfo> results = q.getResultList();

В котором ContactInfo является встраиваемым классом, состоящим из адреса и набора телефонов. Телефон находится в строке.

Любая помощь будет очень признательна.

Я проверяю вопрос, связанный с этой проблемой: JPA - Criteria API и EmbeddedId

Но это не решило мой вопрос.

И я не могу найти ни одного примера кода.

К Джеймсу:

Код объекта, как показано ниже:

    package domain.de1003;

import java.io.IOException;
import java.io.Serializable;
import java.util.List;

import javax.persistence.AttributeOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;

import oracle.eclipselink.coherence.integrated.config.GridCacheCustomizer;

import org.eclipse.persistence.annotations.Customizer;

import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;

@Entity(name="Employee")
@Table(name="EMPLOYEE")
@Customizer(oracle.eclipselink.coherence.integrated.config.GridCacheCustomizer.class)
public class Employee implements PortableObject,Serializable {

private static final long serialVersionUID = 1L;
@Id
@Column(name = "EM_ID")
private long employId;

@Column(name = "FIRSTNAME")
private String firstName;

@Column(name = "LASTNAME")
private String lastName;

@Embedded
@AttributeOverrides({
    @AttributeOverride(name="homePhone", column=@Column(name="HOMEPHONE")),
    @AttributeOverride(name="workPhone", column=@Column(name="WORKPHONE"))
})
private ContactInfo conInfo;

@Version
private long version;

public long getEmployId() {
    return employId;
}

public void setEmployId(long employId) {
    this.employId = employId;
}

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 ContactInfo getConInfo() {
    return conInfo;
}

public void setConInfo(ContactInfo conInfo) {
    this.conInfo = conInfo;
}

public long getVersion() {
    return version;
}

public void setVersion(long version) {
    this.version = version;
}

@Override
public void readExternal(PofReader pofReader) throws IOException {
    employId = pofReader.readLong(1);
    firstName = pofReader.readString(2);
    lastName = pofReader.readString(3);
    version = pofReader.readLong(4);

}

@Override
public void writeExternal(PofWriter pofWriter) throws IOException {
    pofWriter.writeLong(1, employId);
    if(firstName != null) pofWriter.writeString(2, firstName);
    if(lastName != null) pofWriter.writeString(3,lastName);
    pofWriter.writeLong(4, version);
}

@Override
public String toString() {
    return "[" 
    + "employId = " + employId
    + " firstName = " + firstName
    + " lastName = " + lastName
    + " contact inforamtion: " + conInfo
    + "]";
}

}

и контактная информация организации

    package domain.de1003;

import java.io.IOException;
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;

import oracle.eclipselink.coherence.integrated.config.GridCacheCustomizer;

import org.eclipse.persistence.annotations.Customizer;

import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;

@Embeddable
@Customizer(oracle.eclipselink.coherence.integrated.config.GridCacheCustomizer.class)
public class ContactInfo implements PortableObject,Serializable{

private static final long serialVersionUID = 1L;

@Column(name = "ADDRESS")
private String address;

@Column(name = "HOMEPHONE")
private String homePhone;

@Column(name = "WORKPHONE")
private String workPhone;

@Column(name = "CELLPHONE")
private String cellPhone;

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

public String getHomePhone() {
    return homePhone;
}

public void setHomePhone(String homePhone) {
    this.homePhone = homePhone;
}

public String getWorkPhone() {
    return workPhone;
}

public void setWorkPhone(String workPhone) {
    this.workPhone = workPhone;
}

public String getCellPhone() {
    return cellPhone;
}

public void setCellPhone(String cellPhone) {
    this.cellPhone = cellPhone;
}

@Override
public void readExternal(PofReader pofReader) throws IOException {
    address = pofReader.readString(1);
    homePhone = pofReader.readString(2);
    workPhone = pofReader.readString(3);
    cellPhone = pofReader.readString(4);
}

@Override
public void writeExternal(PofWriter pofWriter) throws IOException {
    if(address != null) pofWriter.writeString(1, address);
    if(homePhone != null) pofWriter.writeString(2, homePhone);
    if(workPhone != null) pofWriter.writeString(3, workPhone);
    if(cellPhone != null) pofWriter.writeString(4, cellPhone);
}

@Override
public String toString() {
    return "[" 
    + "address = " + address
    + " homePhone = " + homePhone
    + " workPhone = " + workPhone
    + " cellPhone = " + cellPhone
    + "]";
}

}

Для эквивалентного JQPL

Query query = em.createQuery("ВЫБЕРИТЕ e.conInfo FROM Employee e, где e.employId ‹ 3");

работал.


person DonkeyRider    schedule 16.10.2012    source источник


Ответы (2)


Я попытался воспроизвести это в последней версии EclipseLink (ночная версия 2.5), но не смог. Я подозреваю, что это может быть исправлено с помощью изменений API критериев для добавления поддержки - можете ли вы попробовать, чтобы подтвердить это? Возможно, вам придется отключить кеш, чтобы использовать последнюю версию EclipseLink для тестирования.

person Chris    schedule 17.10.2012
comment
Большое спасибо! Я просто скачал ночную сборку 2.5 и она работает,исключение пропало. Я буду отслеживать изменение кода на этом. Мы по-прежнему применяем EclpseLink2.1.2 в нашем продукте. И я тестировал только последнюю версию v2.4.1, которая все еще выдает исключение. - person DonkeyRider; 18.10.2012

Проверьте, является ли conInfo правильным именем вашего атрибута (включая код вашего объекта).

Работает ли эквивалентный JPQL?

person James    schedule 16.10.2012
comment
Судя по ошибке, похоже, что вы используете join not get, убедитесь, что вы правильно скомпилировали/развернули свой код. В противном случае это может быть ошибка, проверьте, используете ли вы последнюю версию, и зарегистрируйте ошибку. - person James; 17.10.2012