JPA JoinTable无法访问关联实体列表?

时间:2014-06-11 18:18:30

标签: java-ee jpa jax-rs

我是数据库和JPA的初学者。我的问题是,在查询“项目”时,我无法访问该项目的已启用的Api [s]'列表。具体来说,当我使用命名查询来获取结果列表时,代码在此行失败并出现以下错误。

在无状态bean内部的@GET方法行:

List<Project> resultList =  em.createNamedQuery("Project.queryAllUtorid").setParameter("userid", "a valid user I put into the db").getResultList();
List<Api> apis = resultList.get(i).getActiveapis();
System.out.println("Size of list: " + apis.size()); //Fails here

错误:

org.eclipse.persistence.exceptions.DatabaseException: Internal Exception: com.ibm.db2.jcc.am.SqlSyntaxErrorException: "T1.APPID" is not valid in the context where it is used.. SQLCODE=-206, SQLSTATE=42703, DRIVER=4.16.53 Error Code: -206 Call: SELECT t1.APIID, t1.APINAME, t1.BASEURL, t1.QUOTA FROM ACTIVEAPIS t0, DB2ADMIN.APIS t1 WHERE ((t0.PROJECTID = ?) AND (t1.APPID = t0.APIID)) bind => [1 parameter bound] Query: ReadAllQuery(name="activeapis" referenceClass=Api sql="SELECT t1.APIID, t1.APINAME, t1.BASEURL, t1.QUOTA FROM ACTIVEAPIS t0, DB2ADMIN.APIS t1 WHERE ((t0.PROJECTID = ?) AND (t1.APPID = t0.APIID))")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at [internal classes]
at ConsoleREST.queryAllUserProjects(ConsoleREST.java:41)

我了解错误代码-206表示未指定或缺少列。这很明显,因为Select语句正在使用API​​的参数应用于ACTIVEAPIS。我完全不确定如何继续。我查看了各种各样的例子,但是我无法发现差异&#39;在我的代码和示例代码之间。

我有三个表:db2数据库中的PROJECTS,APIS,ACTIVEAPIS。以下是他们的定义:

CREATE TABLE PROJECTS(
PROJECTID   INTEGER     NOT NULL UNIQUE GENERATED ALWAYS AS IDENTITY (START WITH 10000, INCREMENT BY 1),
PROJECTNAME VARCHAR(60) NOT NULL,
USERID      VARCHAR(30) NOT NULL,
CREATEDAT   TIMESTAMP   NOT NULL generated always for each row on update as row change timestamp,
CONSTRAINT FK_USERID FOREIGN KEY (USERID) REFERENCES USERS (USERID)
);

CREATE TABLE APIS(
APIID   INTEGER         GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
APINAME VARCHAR(100)    NOT NULL,
QUOTA   INTEGER         NOT NULL,
BASEURL     VARCHAR(100)    NOT NULL UNIQUE,
CONSTRAINT PK_APIID PRIMARY KEY (APIID)
);

CREATE TABLE ACTIVEAPIS(
APIID       INTEGER NOT NULL,
PROJECTID   INTEGER NOT NULL,
CONSTRAINT PK_APIID_PROJECTID PRIMARY KEY (APIID, PROJECTID),
CONSTRAINT FK_APIID     FOREIGN KEY (APIID)     REFERENCES  APIS        (APIID),
CONSTRAINT FK_PROJECTID FOREIGN KEY (PROJECTID) REFERENCES  PROJECTS    (PROJECTID)
);

实体:

项目实体:

public class Project implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "PROJECTID")
    private Integer projectid;

    @Size(min = 1, max = 60)
    @Column(name = "PROJECTNAME")
    private String projectname;

    @ManyToOne
    @JoinColumn(name = "USERID", referencedColumnName = "USERID")
    private User user;

    @Column(name = "CREATEDAT", insertable=false, updatable=false)
    private Timestamp timestamp;

    //bi-directional many-to-many association to Api
    @ManyToMany
    @JoinTable(name="ACTIVEAPIS",
        joinColumns={
                @JoinColumn(name="PROJECTID", referencedColumnName="PROJECTID")
            }, 
            inverseJoinColumns={
                @JoinColumn(name="APIID", referencedColumnName="APPID")
            }
        )
    private List<Api> activeapis;

public List<Api> getActiveapis() { return activeapis; }

... getters, settings, toString, equals, hashCode
}

Api实体:

@Entity
@Table(name = "APIS", schema="DB2ADMIN")
public class Api implements Serializable {

    private static final long serialVersionUID = 3L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "APIID")
    private Integer apiid;

    @Column(name = "APINAME")
    private String apiname;

    @Column(name = "QUOTA")
    private int quota;

    @NotNull
    @Column(name = "BASEURL", unique = true)
    private String baseurl;

    //bi-directional many-to-many association to Project
    @ManyToMany(mappedBy="activeapis")
    private List<Project> projects;

    public Api() { super(); }

    public Integer getApiid() { 
        if( apiid == null ) return -1;
        return apiid;
    }

JAX-RS设置

@GET
@Path("project")
@Produces("text/json")
public String queryAllUserProjects(@CookieParam(value = "UID") String userid){
    List<Project> resultList =  em.createNamedQuery("Project.queryAllUserid").setParameter("userid", userid).getResultList();
    String json = "[";
    for ( int i = 0; i < resultList.size(); i++ ) {
        List<Api> apis = resultList.get(i).getActiveapis();
        System.out.println("Size of list: " + apis.size());
        System.out.println(apis.get(0).getApiid());

    }
    System.out.println("GET projects query successful");
    return json + "]";
}

最后,namedQuery:

@NamedQueries({
        @NamedQuery(name = "Project.queryAllUserid",
                    query = "SELECT p FROM Project p WHERE p.user.userid LIKE :userid"),
        @NamedQuery(name    = "Project.queryProjectById",
                    query   = "SELECT p FROM Project p WHERE p.projectid LIKE :projectid")
})

我100%确定查询正在正确执行,因为返回了与用户关联的所有其他信息,包括他的所有项目和项目名称以及ID。

我真的很感激帮助,再次感谢!

1 个答案:

答案 0 :(得分:1)

使用JPA进行的第一次调试应该总是在控制台中粘贴SQL,用合理的值替换占位符?并观察会发生什么。其次应检查数据库错误信息。

在我的误导评论之后,我只是用Google搜索&#34; DB2&#34; + [错误消息]并转到http://www-01.ibm.com/support/docview.wss?uid=swg21236040,其中包含以下文本:

  

SQLSTATE 42703表示:

     

检测到未定义的列,属性或参数名称。

仔细检查您的DDL,碰巧在您的ACTIVEAPIS表(也未在APIS)表中没有定义APPID列。有一个APIID,但是......