如何使用JPA Native Query正确访问where子句中的varray列?

时间:2018-03-21 19:55:19

标签: java oracle jpa

所以我正在创建一个按钮,使用CustomerId,电话号码或客户电子邮件检索一位客户的结果。我是JPA的新手,直到最近我才听说'varray'数据类型。

这是我正在使用的方法的代码:

public Customer findOneCustomerByUniqueValue(String queryValue) { 
    Customer querySingleResult = null;  
    try {
        if (queryValue.matches("[0-9]+")) {
            querySingleResult = entityManager.createQuery(
                "SELECT c FROM Customer c "
              + "WHERE c.customerId = :queryValue",
                Customer.class)
                .setParameter("queryValue", Long.parseLong(queryValue))
                .getSingleResult();
            this.findOneCustomer(Integer.parseInt(queryValue));
        }
        else {
            Object[] row = (Object[]) entityManager.createNativeQuery(
                "SELECT * FROM CUSTOMERS c, TABLE(PHONE_NUMBERS) p "
              + "WHERE c.CUST_EMAIL = :queryValue OR p.COLUMN_VALUE = :queryValue")
                .setParameter("queryValue", queryValue)
                .getSingleResult();     
            if (row != null) {
                querySingleResult = new Customer();
                querySingleResult.setCustomerId((Long) row[0]);
                querySingleResult.setCustFirstName((String) row[1]);
                querySingleResult.setCustLastName((String) row[2]);
                querySingleResult.setCustAddress((CustomerAddress) row[3]);
                querySingleResult.setPhoneNumbers((List<String>) row[4]);
                querySingleResult.setNlsLanguage((String) row[5]);
                querySingleResult.setNlsTerritory((String) row[6]);
                querySingleResult.setCreditLimit((BigDecimal) row[7]);
                querySingleResult.setCustEmail((String) row[8]);
                querySingleResult.setAccountManager((Employee) row[9]);
                querySingleResult.setDateOfBirth((Date) row[10]);
                querySingleResult.setMaritalStatus((String) row[11]);
                querySingleResult.setGender((String) row[12]);
                querySingleResult.setIncomeLevel((String) row[13]);
            }

        }

    } catch(NoResultException e) {
        querySingleResult = null;
    }

    return querySingleResult;
}

使用我的Object数组声明中的当前查询,我收到错误:

Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: 2002

但如果我将p.COLUMN_VALUE更改为p.COLUMN_NAME,我的错误将更改为:

Caused by: Error : 904, Position : 78, Sql = SELECT * FROM CUSTOMERS c, TABLE(PHONE_NUMBERS) p WHERE c.CUST_EMAIL = :1 OR p.COLUMN_NAME = :2 , OriginalSql = SELECT * FROM CUSTOMERS c, TABLE(PHONE_NUMBERS) p WHERE c.CUST_EMAIL = ? OR p.COLUMN_NAME = ?, Error Msg = ORA-00904: "P"."COLUMN_NAME": invalid identifier

我做错了什么?

1 个答案:

答案 0 :(得分:0)

最可能的原因是你正在做一个select&#34; *&#34;,所以即使你使用的是TABLE函数,你仍然会得到返回的对象类型。

例如

SQL> create or replace type numlist as varray(5) of number;
  2  /

Type created.

SQL>
SQL>
SQL> create table cust ( cid int, phone numlist );

Table created.

SQL>
SQL> insert into cust values (1, numlist(1,2,3,4));

1 row created.

SQL> insert into cust values (2, numlist(5,6,7,8,9));

1 row created.


SQL>
SQL> select *
  2  from  cust c, table(c.phone) p
  3  where c.cid = 1 or p.column_value = 6;

       CID PHONE                          COLUMN_VALUE
---------- ------------------------------ ------------
         1 NUMLIST(1, 2, 3, 4)                       1
         1 NUMLIST(1, 2, 3, 4)                       2
         1 NUMLIST(1, 2, 3, 4)                       3
         1 NUMLIST(1, 2, 3, 4)                       4
         2 NUMLIST(5, 6, 7, 8, 9)                    6

您可能只想选择所需的列,从而避免返回复杂的对象类型

SQL>
SQL> select c.cid, p.column_value
  2  from  cust c, table(c.phone) p
  3  where c.cid = 1 or p.column_value = 6;

       CID COLUMN_VALUE
---------- ------------
         1            1
         1            2
         1            3
         1            4
         2            6