The Source for Java Technology Collaboration

Home » java.net Forums » GlassFish » GlassFish

Thread: EJBQL Exception

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
This question is answered.

Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 9 - Last Post: May 1, 2007 10:49 PM by: mvatkina
drscoville

Posts: 5
EJBQL Exception
Posted: Apr 30, 2007 6:04 PM
 
  Click to reply to this thread Reply

Hi,

I'm a Java Persistence newbie having a massive problem spotting the error that is triggering an Unknown state or association field exception.

I have created a Persistence Entity with the following excerpted code, plus the necessary get/set methods:

@Entity
public class Seller implements java.io.Serializable {

private String sellerID;
private String selcatID;
private String name;

public Seller() { }
public Seller(String sellerID, String selcatID, String name)
{
this.sellerID = sellerID;
this.selcatID = selcatID;
this.name = name;
}

In another Java file, I have a method that references the selcatID attribute of the Seller entity:

@SuppressWarnings("unchecked")
public List<Seller> getSellersBySelCatVLH(String selCatID, int start,
int chunkSize){
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("SELECT s FROM Seller s, SelCat t WHERE " +
"s.selcatID = t.selcatID AND t.selcatID = :selcatID AND s.disabled = 0" +
" ORDER BY s.name");
List<Seller> sellers = query.setParameter("selcatID",selCatID).setFirstResult(start).setMaxResults(chunkSize).getResultList();
em.close();
return sellers;
}

Note that the case usage in the selcatID call in the method matches the case used in the Entity definition code. Yet I continue to get this exception:

Exception [TOPLINK-8030] (Oracle TopLink Essentials - 2006.8 (Build 060830)): oracle.toplink.essentials.exceptions.EJBQLException
Exception Description: Unknown state or association field [selcatID] of class [...Seller].

I have been through the server log stack trace and confirmed that this is the only method cited in the trace that references this attribute.

Can anyone spot what I am missing?

Thanks in advance for any guidance.

mvatkina

Posts: 755
Re: EJBQL Exception
Posted: Apr 30, 2007 7:35 PM   in response to: drscoville
 
  Click to reply to this thread Reply

I don't see any annotations that define wich fields or properties represent the state of the entity. Can it be the cause of the problem?

thanks,
-marina

drscoville

Posts: 5
Re: EJBQL Exception
Posted: Apr 30, 2007 8:16 PM   in response to: mvatkina
 
  Click to reply to this thread Reply

Thanks for your reply. The Java EE Tutorial chapters on Persistence say that only two attribution tags are required: @Entity (which I list above) and @Id, which I did not list earlier but which is directed to my primary key as follows:

@Id
public String getSellerID() {
return sellerID;
}

Are there more that are required? Sorry if this is obtuse.

jshevland

Posts: 6
Re: EJBQL Exception
Posted: Apr 30, 2007 8:47 PM   in response to: drscoville
Helpful
  Click to reply to this thread Reply

(Replied on the mailing list and assumed it was bi-directional, doesn't seem so).

You'll need to add @Column attributes for the standard (non-relation) columns, and if you want JPA to do the actual leg-work for you, define a ManyToOne or OneToMany to define the relationships e.g.

@Entity public class Seller ... {
...
@ManyToOne
@JoinColumn(name="selcatID")
private SelCat category;
...
}

Then a query like:

select slr
from Seller slr
where slr.category = :category
and slr.disabled = false
and slr.category.someProperty = :someRestriction ...

mvatkina

Posts: 755
Re: EJBQL Exception
Posted: Apr 30, 2007 8:53 PM   in response to: jshevland
 
  Click to reply to this thread Reply

While @ManyToOne (or any other relationship annotation) is required, the @Column or @JoinColumn are optional - if your mapping is the same as the defaults defined in the spec, you don't need them.

Regards,
-marina

drscoville

Posts: 5
Re: EJBQL Exception
Posted: Apr 30, 2007 10:28 PM   in response to: jshevland
 
  Click to reply to this thread Reply

Thanks to the two people who have made suggestions.

I tried adding the @ManyToOne and @JoinColumns attributes as suggested below and revising my query as you suggested on the mailing list. Unfortunately, it seems to break the application, as it would not run with Seller defined in that manner. (At one point the application server even hung, so I had to reinstall, thus the lengthy delay to my reply). I had to roll back to my original definition to restore the application to run at all, though it still leaves me with the Exception regarding the query.

In hopes it will help generate more ideas, here are the entire definition files for the Entities Seller and SelCat. I followed the form used in a Java reference application from Sun, which I am coming to see is not well-formed.

Thanks again for the suggestions to this point.

Seller.java:

package com.sun.javaee.blueprints.petstore.model;

import com.sun.javaee.blueprints.petstore.util.PetstoreUtil;
import java.util.ArrayList;
import java.util.Arrays;
import static javax.persistence.CascadeType.ALL;
import java.util.Collection;
import java.util.Vector;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.TableGenerator;

/**@NamedQueries(
{ @NamedQuery(
name="Seller.getSellersPerDesignation",
query="SELECT s FROM Seller s WHERE s.selcatid = :selcatid and s.disabled = 0"
),
@NamedQuery(
name="Seller.getAllZipCityState",
query="SELECT z FROM ZipLocation z"
)
}
)
*/

@Entity
public class Seller implements java.io.Serializable {

private String sellerID;
private String selcatID;
private String name;
private Address address;
private SellerContactInfo contactInfo;
private int disabled;


public Seller() { }
public Seller(String selcatID, String name,
Address address, SellerContactInfo contactInfo)
{
this.selcatID = selcatID;
this.name = name;
this.address = address;
this.contactInfo = contactInfo;
this.disabled = 0;
}

@TableGenerator(name="SELLER_ID_GEN",
table="ID_GEN",
pkColumnName="GEN_KEY",
valueColumnName="GEN_VALUE",
pkColumnValue="SELLER_ID",
allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE,generator="SELLER_ID_GEN")

@Id
public String getSellerID() {
return sellerID;
}

public String getSelCatID() {
return selcatID;
}

public String getName() {
return name;
}

@OneToOne(cascade={CascadeType.PERSIST})
public Address getAddress() {
return address;
}

@OneToOne(cascade={CascadeType.PERSIST})
public SellerContactInfo getContactInfo() {
return contactInfo;
}

public int getDisabled() {
return disabled;
}

public void setSellerID(String sellerID) {
this.sellerID = sellerID;
}
public void setSelCatID(String selcatID) {
this.selcatID = selcatID;
}
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public void setContactInfo(SellerContactInfo contactInfo) {
this.contactInfo = contactInfo;
}
public void setDisabled(int disabled) {
this.disabled = disabled;
}

/**
* This method checks to make sure the class values are valid
*
* @return Message(s) of validation errors or and empty array (zero length) if class is valid
*/
public String[] validateWithMessage() {
ArrayList<String> valMess=new ArrayList<String>();

if(name == null || name.equals("")) {
valMess.add(PetstoreUtil.getMessage("invalid_contact_firstname"));
}

// to make sure seller is valid, have to check address and contact also
valMess.addAll(Arrays.asList(contactInfo.validateWithMessage()));
valMess.addAll(Arrays.asList(address.validateWithMessage()));

return valMess.toArray(new String[valMess.size()]);
}

}


SelCat.java:

package com.sun.javaee.blueprints.petstore.model;

import com.sun.javaee.blueprints.petstore.util.PetstoreUtil;
import java.util.ArrayList;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.TableGenerator;

@Entity
public class SelCat implements java.io.Serializable {

private String selcatID;
private String name;

public SelCat() { }
public SelCat(String name) {
this.name = name;
}

@TableGenerator(name="SELCAT_ID_GEN",
table="ID_GEN",
pkColumnName="GEN_KEY",
valueColumnName="GEN_VALUE",
pkColumnValue="SELCAT_ID",
allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE,generator="SELCAT_ID_GEN")

@Id
public String getSelCatID() {
return selcatID;
}

public String getName() {
return name;
}

public void setSelCatID(String selcatID) {
this.selcatID = selcatID;
}
public void setName(String name) {
this.name = name;
}

/**
* This method checks to make sure the class values are valid
*
* @return Message(s) of validation errors or and empty array (zero length) if class is valid
*/
public String[] validateWithMessage() {
ArrayList<String> valMess=new ArrayList<String>();

// make sure make and address is entered
if(name == null || name.equals("")) {
valMess.add(PetstoreUtil.getMessage("invalid_contact_lastname"));
}

return valMess.toArray(new String[valMess.size()]);
}

}

mvatkina

Posts: 755
Re: EJBQL Exception
Posted: Apr 30, 2007 10:42 PM   in response to: drscoville
Correct
  Click to reply to this thread Reply

IF everything is exactly as you specify, I might have a clue - the names are case sensitive, so getSelCatID means 'selCatID, not 'selcatID', nor 'selcatid'.

Regards,
-marina

Message was edited by: mvatkina

drscoville

Posts: 5
Re: EJBQL Exception
Posted: May 1, 2007 8:33 PM   in response to: jshevland
 
  Click to reply to this thread Reply

Thanks much for the suggestion. It took me a while to implement as initially addition of the ManyToOne attribute caused the app server to hang. I eventually realized this was because the SelCat entity was referenced to the Seller entity only by its ID attribute (a String). I replaced this with an object reference, which resolved that problem.

If I may ask one follow up question, to what entity does the name in the JoinColumn annotation refer? Should I list the name of the primary key of the SelCat entity or the name of the SelCat foreign key column in the Seller (or SelCat) SQL definition? I've been hunting for an answer in documentation and the web and can't find one.

mvatkina

Posts: 755
Re: EJBQL Exception
Posted: May 1, 2007 10:49 PM   in response to: drscoville
 
  Click to reply to this thread Reply

I suggest to use the table in the spec and it's default explanations for the annotations details. E.g. for the JoinColumn the 'name' refers to the FK column name in this table (i.e. table that this side is mapped to), and the 'referencedColumnName' to the PK column on the other side.

Please keep in mind that if you use TopLink Essentials (the default persistence provider in GlassFish), it converts all column names that it calculates by the default rules to upper case . So be careful to match those names if you provide only partial mappings.

On the other hand, if you let the provider generate the DDL for you, you don't need to specify any mapping, unless a resulting name is a reserved SQL word.

HTH,
-marina

Message was edited by: mvatkina

mvatkina

Posts: 755
Re: EJBQL Exception
Posted: Apr 30, 2007 8:50 PM   in response to: drscoville
 
  Click to reply to this thread Reply

The tutorial is correct. As you put the @Id annotation on the getter, you are using property-based access type, and for the 'selcatID' you'll have get/setSelcatID() methods. Is it the case?

thanks,
-marina




 XML java.net RSS