2013-04-27 31 views
6

Tôi hy vọng Tôi chỉ làm điều gì đó ngớ ngẩn ở đây ...EclipseLink JPA "không hợp lệ bảng trong bối cảnh này" với @OneToMany Bản đồ

Tôi đang cố gắng để thiết lập các chú thích JPA cho một Map<String, Phone> và nhận được theo dõi ngăn xếp sau.

Exception [EclipseLink-6069] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.QueryException 
Exception Description: The field [EMPLOYEE.PHONE_TYPE] in this expression has an invalid table in this context. 
Query: ReadAllQuery(name="phones" referenceClass=Phone) 
    at org.eclipse.persistence.exceptions.QueryException.invalidTableForFieldInExpression(QueryException.java:739) 
    at org.eclipse.persistence.internal.expressions.FieldExpression.validateNode(FieldExpression.java:281) 
    at org.eclipse.persistence.expressions.Expression.normalize(Expression.java:3259) 
    at org.eclipse.persistence.internal.expressions.DataExpression.normalize(DataExpression.java:369) 
    at org.eclipse.persistence.internal.expressions.FieldExpression.normalize(FieldExpression.java:208) 
    at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1377) 
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildNormalSelectStatement(ExpressionQueryMechanism.java:546) 
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareSelectAllRows(ExpressionQueryMechanism.java:1700) 
    at org.eclipse.persistence.queries.ReadAllQuery.prepareSelectAllRows(ReadAllQuery.java:721) 
    at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:657) 
    at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:614) 
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:883) 
    at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:575) 
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:820) 
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1109) 
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:393) 
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1197) 
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2875) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584) 
    at org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiate(QueryBasedValueHolder.java:112) 
    at org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiate(QueryBasedValueHolder.java:99) 
    at org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:88) 
    at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiateImpl(UnitOfWorkValueHolder.java:161) 
    at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiate(UnitOfWorkValueHolder.java:222) 
    at org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:88) 
    at org.eclipse.persistence.indirection.IndirectMap.buildDelegate(IndirectMap.java:110) 
    at org.eclipse.persistence.indirection.IndirectMap.getDelegate(IndirectMap.java:330) 
    at org.eclipse.persistence.indirection.IndirectMap.size(IndirectMap.java:637) 
    at org.eclipse.persistence.internal.queries.MapContainerPolicy.sizeFor(MapContainerPolicy.java:830) 
    at org.eclipse.persistence.internal.indirection.TransparentIndirectionPolicy.instantiateObject(TransparentIndirectionPolicy.java:386) 
    at org.eclipse.persistence.mappings.ForeignReferenceMapping.buildCloneFromRow(ForeignReferenceMapping.java:285) 
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildAttributesIntoWorkingCopyClone(ObjectBuilder.java:1594) 
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneFromRow(ObjectBuilder.java:1741) 
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:668) 
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:605) 
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:564) 
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.buildObject(ObjectLevelReadQuery.java:777) 
    at org.eclipse.persistence.queries.ReadAllQuery.registerResultInUnitOfWork(ReadAllQuery.java:783) 
    at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:434) 
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1150) 
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:852) 
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1109) 
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:393) 
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1197) 
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2875) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1549) 
    at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:231) 
    at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:411) 
    at aaa.Test.main(Test.java:20) 

Các bảng được tạo ra trông giống như:

EMP_PHONE 
================================= 
EMP_ID PHONES_ID PHONE_TYPE 
------ --------- ---------- 
42  1   NULL 


EMPLOYEE 
================================= 
ID 
-- 
42 


PHONE 
================================= 
ID NUM 
-- -------- 
1  867-5309 

Các NULLPHONE_TYPE dường như cho tôi biết một cái gì đó sôi nổi đang diễn ra, và cách mà EclipseLink đang tìm kiếm EMPLOYEE.PHONE_TYPE làm cho tôi nghĩ rằng nó đang nghĩ về mối quan hệ từ PHONE ->EMPLOYEE thay vì cách khác.

thực thể JPA được định nghĩa như sau. Bản đồ điện thoại là một chiều, và các đối tượng điện thoại nên được chia sẻ bởi nhiều nhân viên (không phải loại thực tế của tôi, nhưng ví dụ đơn giản này chứng tỏ vấn đề)

@Entity 
public class Employee { 
    @Id private long id; 

    @OneToMany(cascade=CascadeType.ALL) 
    @JoinTable(name="EMP_PHONE", [email protected](name="EMP_ID")) 
    @MapKeyColumn(name="PHONE_TYPE") 
    private Map<String, Phone> phones = new HashMap<String, Phone>(); 

    public Employee() {} 
    public Employee(long id) { 
     this.id = id; 
    } 
    public long getId() { 
     return id; 
    } 
    public Map<String, Phone> getPhones() { 
     return phones; 
    } 
} 

@Entity 
public class Phone { 
    @Id 
    private long id; 
    private String num; 

    public String getNum() { 
     return num; 
    } 
    public Phone() {} 
    public Phone(String num) { 
     this.num = num; 
    } 
    public Phone(long id, String num) { 
     this.id = id; 
     this.num = num; 
    } 
    public long getId() { 
     return id; 
    } 
} 

bằng cách sử dụng mã kiểm tra sau

EntityManagerFactory factory = Persistence.createEntityManagerFactory("test"); 
EntityManager em = factory.createEntityManager(); 
Employee employee = new Employee(42); 
// exception will occur with or without phones added to the map 
employee.getPhones().put("home", new Phone(1, "867-5309")); 
em.getTransaction().begin(); 
em.persist(employee); 
em.getTransaction().commit(); 

Query q = em.createQuery("select o from Employee o"); 
q.setHint("javax.persistence.cache.storeMode", "REFRESH"); 
q.getResultList(); // EXCEPTION THROWN HERE 

và kiên trì .xml:

<?xml version='1.0' encoding='UTF-8' ?> 
<persistence xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
    xsi:schemaLocation='http://java.sun.com/xml/ns/persistence 
      http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd' 
    version='2.0' xmlns='http://java.sun.com/xml/ns/persistence'> 
    <persistence-unit name='test' transaction-type='RESOURCE_LOCAL'> 
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
     <class>aaa.Phone</class> 
     <class>aaa.Employee</class> 
     <shared-cache-mode>NONE</shared-cache-mode> 
     <properties> 
      <property name='javax.persistence.jdbc.user' value='uuuuuuuu' /> 
      <property name='javax.persistence.jdbc.password' value='pppppppp' /> 
      <property name='javax.persistence.jdbc.driver' 
         value='oracle.jdbc.driver.OracleDriver' /> 
      <property name='javax.persistence.jdbc.url' 
         value='jdbc:oracle:thin:@localhost:1521:xe' /> 
      <property name='eclipselink.ddl-generation' 
         value='drop-and-create-tables' /> 
      <property name='eclipselink.ddl-generation.output-mode' value='database' /> 
     </properties> 
    </persistence-unit> 
</persistence> 

Tôi đang chạy trên Windows 7, sử dụng Oracle XE 11g làm cơ sở dữ liệu. Cảm ơn trước cho bất kỳ hiểu biết!

Trả lời

10

này trông giống như EclipseLink lỗi 364922:

An entity with uni-directional OneToMany property and @MapKeyColumn annotation has the correct database tables created, with the mapping table containing a "key column, but persisting an entity only populates the id columns and not the key column. The persist operation does not throw an error, but subsequent queries soon fail with the following error: Exception Description: The field [ORGANIZATION.MAILINGADDRESSES_KEY] in this expression has an invalid table in this context.

Đối với những gì nó có giá trị, tôi đã kiểm tra mã của bạn sử dụng Hibernate/H2 và nó hoạt động tốt.

CẬP NHẬT

tôi chỉ thử nghiệm này với EclipseLink. Nếu bạn đặt bảng một cách rõ ràng cho số MapKeyColumn, khóa sẽ được điền chính xác. tức là:

@MapKeyColumn(name="PHONE_TYPE", table="EMP_PHONE")

+0

Cảm ơn bạn rất nhiều! Tôi nghĩ rằng đó là một sự kết hợp của các tùy chọn tôi đã không cố gắng;) Ước gì tôi đã nhìn thấy lỗi đó khi tôi đang tìm kiếm. –

+0

Tôi đã thử nghiệm nó trong ứng dụng thực sự của tôi và nó hoạt động hoàn hảo. Cảm ơn một lần nữa –

+0

Vui vì nó đã giúp. Tôi đã đối mặt với chia sẻ của tôi về các vấn đề khó nắm bắt với việc triển khai JPA và tôi biết rằng họ có thể thúc đẩy bạn các loại hạt;) – pwrex

Các vấn đề liên quan