有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么oracle表ALL_TAB_列的本机查询由于列无效而失败?

为什么我在spring boot hibernate createNativeQuery中出现这个错误Invalid column name?我正在尝试从oracle数据库获取表信息。我把我的查询放在db eaver它成功了,告诉我本地查询的最佳实践是什么,请

Hibernate: SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE FROM ALL_TAB_COLUMNS WHERE TABLE_NAME='BPN_AKTA'
2020-09-25 10:27:53.005  WARN 60208 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 17006, SQLState: 99999
2020-09-25 10:27:53.005 ERROR 60208 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : Invalid column name
2020-09-25 10:27:53.006 ERROR 60208 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query] with root cause

java.sql.SQLException: Invalid column name
Query q= em.createNativeQuery("SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE FROM ALL_TAB_COLUMNS WHERE TABLE_NAME='PC'",QueryTableAttModel.class);
List<QueryTableAttModel> tableColl =  q.getResultList();

我的模型

@Entity(name="ALL_TAB_COLUMNS")
public class QueryTableAttModel {

    public String getTABLE_NAME() {
        return TABLE_NAME;
    }

    public void setTABLE_NAME(String TABLE_NAME) {
        this.TABLE_NAME = TABLE_NAME;
    }


    public String getCOLUMN_NAME() {
        return COLUMN_NAME;
    }

    public void setCOLUMN_NAME(String COLUMN_NAME) {
        this.COLUMN_NAME = COLUMN_NAME;
    }


    public String getDATA_TYPE() {
        return DATA_TYPE;
    }

    public void setDATA_TYPE(String DATA_TYPE) {
        this.DATA_TYPE = DATA_TYPE;
    }

    private String TABLE_NAME;
    private String COLUMN_NAME;
    private String DATA_TYPE;
    private String id;

    @Id
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

共 (1) 个答案

  1. # 1 楼答案

    问题是表ALL_TAB_COLUMNS没有单列主键。应该使用基于OWNERTABLE_NAMECOLUMN_NAME列的复合主键

    例如,可以使用@IdClassannotation进行复合主键映射:

    @Entity
    @Table(name = "ALL_TAB_COLUMNS")
    @IdClass(QueryTableAttModelPK.class)
    public class QueryTableAttModel
    {
       private String owner;
       private String tableName;
       private String columnName;
       private String dataType;
       
       public QueryTableAttModel()
       {
       }
       
       @Id
       @Column(name = "OWNER")
       public String getOwner()
       {
          return owner;
       }
       public void setOwner(String owner)
       {
          this.owner = owner;
       }
    
       @Id
       @Column(name = "TABLE_NAME")
       public String getTableName()
       {
          return tableName;
       }
       public void setTableName(String tableName)
       {
          this.tableName = tableName;
       }
    
       @Id
       @Column(name = "COLUMN_NAME")
       public String getColumnName()
       {
          return columnName;
       }
       public void setColumnName(String columnName)
       {
          this.columnName = columnName;
       }
    
       @Column(name = "DATA_TYPE")
       public String getDataType()
       {
          return dataType;
       }
       public void setDataType(String dataType)
       {
          this.dataType = dataType;
       }
    }
    

    其中QueryTableAttModelPK类是

    import java.io.Serializable;
    import java.util.Objects;
    
    public class QueryTableAttModelPK implements Serializable
    {
       private String owner;
       private String tableName;
       private String columnName;
       
       public QueryTableAttModelPK()
       {
       }
       
       public QueryTableAttModelPK(String owner, String tableName, String columnName)
       {
          this.owner = owner;
          this.tableName = tableName;
          this.columnName = columnName;
       }
    
       public String getOwner()
       {
          return owner;
       }
       public void setOwner(String owner)
       {
          this.owner = owner;
       }
    
       public String getTableName()
       {
          return tableName;
       }
       public void setTableName(String tableName)
       {
          this.tableName = tableName;
       }
    
       public String getColumnName()
       {
          return columnName;
       }
       public void setColumnName(String columnName)
       {
          this.columnName = columnName;
       }
       
       @Override
       public boolean equals(Object obj) {
          if (this == obj) return true;
          if (obj == null) return false;
          if (getClass() != obj.getClass()) return false;
          
          QueryTableAttModelPK other = (QueryTableAttModelPK) obj;
          return Objects.equals(owner, other.owner) 
              && Objects.equals(tableName, other.tableName)
              && Objects.equals(columnName, other.columnName);
       }
    
       @Override
       public int hashCode() {
          return Objects.hash(owner, tableName, columnName);
       }
    }
    

    然后可以使用本机查询:

    List<QueryTableAttModel> results = em.createNativeQuery(
       "select OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE from ALL_TAB_COLUMNS where TABLE_NAME = :table",
       QueryTableAttModel.class)
    .setParameter("table", "ALL_TAB_COLUMNS")
    .getResultList();
    

    jpql/hql查询:

    List<QueryTableAttModel> results = em.createQuery(
       "select q from QueryTableAttModel q where q.tableName = :table",
       QueryTableAttModel.class)
    .setParameter("table", "ALL_TAB_COLUMNS")
    .getResultList();
    

    或者通过PK查找实体:

    QueryTableAttModel qTable = em.find(
       QueryTableAttModel.class,
       new QueryTableAttModelPK("SYS", "ALL_TAB_COLUMNS", "CHAR_LENGTH")
    );