Hibernate HQL - 不存在抛出 org.hibernate.exception.SQLGrammarException 的条件:

Posted

技术标签:

【中文标题】Hibernate HQL - 不存在抛出 org.hibernate.exception.SQLGrammarException 的条件:【英文标题】:Hibernate HQL - not exists condition throwing org.hibernate.exception.SQLGrammarException: 【发布时间】:2017-03-17 15:50:58 【问题描述】:

我有 3 个表(多对多条件)- Stock、Categories 和一个中间 Stock_Category。

在 Hibernate 中,我有 2 个实体 - 具有一组类别的股票和具有一组股票的类别实体。

现在我想获取不属于特定类别的所有股票,由类别名称标识。

我有以下用 HQL 编码的相关子查询:

Query query = session.createQuery("Select s from Stock s join fetch                   s.categories c " +
                "where not exists (Select cs from Category cs " +
                "where s in cs.stocks and cs.categoryname = :categoryname)");
        query.setParameter("categoryname", "MATTEL");

似乎 hibernate 可以理解查询,因为它在控制台中提供了自己的解释版本,但仍然抛出 Sql 异常。缺失的因素是什么?

由休眠提供:

Hibernate: 
/* Select
    s 
from
    Stock s 
join
    fetch s.categories c 
where
    not exists (
        Select
            cs 
        from
            Category cs 
        where
            s in cs.stocks 
            and cs.categoryname = :categoryname
    ) */ select
        stock0_.STOCK_ID as STOCK_ID1_1_0_,
        categories1_.CATEGORY_ID as CATEGORY_ID1_0_1_,
        stock0_.STOCK_CODE as STOCK_CODE2_1_0_,
        stock0_.STOCK_NAME as STOCK_NAME3_1_0_,
        categories1_.CATEGORY_NAME as CATEGORY_NAME2_0_1_,
        categories1_.CATEGORY_DESC as CATEGORY_DESC3_0_1_,
        categories1_.STOCK_ID as STOCK_ID4_1_0__,
        categories1_.CATEGORY_ID as CATEGORY_ID1_0_0__ 
    from
        STOCK stock0_ 
    inner join
        CATEGORY categories1_ 
            on stock0_.STOCK_ID=categories1_.STOCK_ID 
    where
        not (exists (select
            category2_.CATEGORY_ID 
        from
            CATEGORY category2_,
            STOCK stocks3_ 
        where
            category2_.CATEGORY_ID=stocks3_.CATEGORY_ID 
            and (stock0_.STOCK_ID in (.)) 
            and category2_.CATEGORY_NAME=?))

这是 CATEGORY 表的实体类:

@Entity
@Table(name = "category")
public class Category implements java.io.Serializable 

private Integer categoryId;
private String categoryname;
private String categorydesc;
private Set<Stock> stocks = new HashSet<Stock>(0);

public Category() 


public Category(String name, String desc) 
    this.categoryname = name;
    this.categorydesc = desc;


public Category(String name, String desc, Set<Stock> stocks) 
    this.categoryname = name;
    this.categorydesc = desc;
    this.stocks = stocks;


@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "CATEGORY_ID", unique = true, nullable = false)
public Integer getCategoryId() 
    return this.categoryId;


public void setCategoryId(Integer categoryId) 
    this.categoryId = categoryId;


@Column(name = "CATEGORY_NAME", nullable = false, length = 10)
public String getCategoryname() 
    return this.categoryname;


public void setCategoryname(String name) 
    this.categoryname = name;


@Column(name = "[CATEGORY_DESC]", nullable = false)
public String getCategorydesc() 
    return this.categorydesc;


public void setCategorydesc(String desc) 
    this.categorydesc = desc;


@ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories")
public Set<Stock> getStocks() 
    return this.stocks;


public void setStocks(Set<Stock> stocks) 
    this.stocks = stocks;



这是 Category.hbm.xml 中的映射:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Mar 17, 2017 8:59:40 AM by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="com.mkyong.stock.Category" table="CATEGORY">
    <id name="categoryId" type="java.lang.Integer">
        <column name="CATEGORY_ID" />
        <generator class="assigned" />
    </id>
    <property name="categoryname" type="java.lang.String">
        <column name="CATEGORY_NAME" />
    </property>
    <property name="categorydesc" type="java.lang.String">
        <column name="CATEGORY_DESC" />
    </property>
    <set name="stocks" table="STOCK" inverse="false" lazy="true">
        <key>
            <column name="CATEGORY_ID" />
        </key>
        <one-to-many class="com.mkyong.stock.Stock" />
    </set>
</class>
</hibernate-mapping>

这是 STOCK 表的实体类:

@Entity
@Table(name = "stock", uniqueConstraints = 
    @UniqueConstraint(columnNames = "STOCK_NAME"),
    @UniqueConstraint(columnNames = "STOCK_CODE") ) 
public class Stock implements java.io.Serializable 

private Integer stockId;
private String stockCode;
private String stockName;
private Set<Category> categories = new HashSet<Category>(0);

public Stock() 


public Stock(int stockid, String stockCode, String stockName) 
    this.stockId = stockid;
    this.stockCode = stockCode;
    this.stockName = stockName;


public Stock(String stockCode, String stockName, Set<Category> categories) 
    this.stockCode = stockCode;
    this.stockName = stockName;
    this.categories = categories;


@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "STOCK_ID", unique = true, nullable = false)
public Integer getStockId() 
    return this.stockId;


public void setStockId(Integer stockId) 
    this.stockId = stockId;


@Column(name = "STOCK_CODE", unique = true, nullable = false, length = 10)
public String getStockCode() 
    return this.stockCode;


public void setStockCode(String stockCode) 
    this.stockCode = stockCode;


@Column(name = "STOCK_NAME", unique = true, nullable = false, length = 20)
public String getStockName() 
    return this.stockName;


public void setStockName(String stockName) 
    this.stockName = stockName;


@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "stock_category", joinColumns =  
        @JoinColumn(name = "STOCK_ID", nullable = false, updatable = false) , 
        inverseJoinColumns =  @JoinColumn(name = "CATEGORY_ID", 
                nullable = false, updatable = false) )
public Set<Category> getCategories() 
    return this.categories;


public void setCategories(Set<Category> categories) 
    this.categories = categories;



这是 Stock.hbm.xml 中的映射

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Mar 17, 2017 8:59:40 AM by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="com.mkyong.stock.Stock" table="STOCK">
    <id name="stockId" type="java.lang.Integer">
        <column name="STOCK_ID" />
        <generator class="assigned" />
    </id>
    <property name="stockCode" type="java.lang.String">
        <column name="STOCK_CODE" />
    </property>
    <property name="stockName" type="java.lang.String">
        <column name="STOCK_NAME" />
    </property>
    <set name="categories" table="CATEGORY" inverse="false" lazy="true">
        <key>
            <column name="STOCK_ID" />
        </key>
        <one-to-many class="com.mkyong.stock.Category" />
    </set>
</class>
</hibernate-mapping>

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory name="">
  <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
  <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
  <property name="hibernate.connection.username">system</property>
  <property name="hibernate.connection.password">anishakshi1</property>
  <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
  <property name="show_sql">true</property>
  <property name="format_sql">true</property>
  <property name="use_sql_comments">true</property>
  <mapping resource="com/mkyong/stock/Category.hbm.xml"/>
  <mapping resource="com/mkyong/stock/Stock.hbm.xml"/>
  </session-factory>
 </hibernate-configuration>

【问题讨论】:

【参考方案1】:

这样的属性更新

property name="hibernate.hbm2ddl.auto">验证

【讨论】:

【参考方案2】:

我认为您可以加入而不是 in 声明:

"Select s from Stock s join fetch s.categories c " +
"where not exists (Select cs from Category cs inner join cs.stocks ss " +
"where s.id = ss.id and cs.categoryname = :categoryname)"

更新

您的 xml 映射是错误的。它们没有指定多对多映射。 您的注释似乎很好:

1) 移除这些属性:

<mapping resource="com/mkyong/stock/Category.hbm.xml"/>
  <mapping resource="com/mkyong/stock/Stock.hbm.xml"/>

2) 将此属性添加到您的 sessionFactory 配置中:

<property name="packagesToScan" value="com.mkyong"/>

【讨论】:

我在尝试 OP 中给出的 HQL 之前尝试过。 Hibernate 给我这个内部连接错误: ERROR: ORA-00904: "CATEGORIES1_"."STOCK_ID": invalid identifier 尝试添加这两个表的实体映射 添加了实体类及其映射。 不确定为什么要使用注释和 hbm 文件.. 尝试仅使用注释并暂时省略 hbm 文件 我是 Hibernate 的新手,这是迄今为止我的导师教给我的唯一方法......

以上是关于Hibernate HQL - 不存在抛出 org.hibernate.exception.SQLGrammarException 的条件:的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 抛出奇怪的错误:类未映射

org.hibernate.hql.QueryExecutionRequestException:org.hibernate.hql.QueryExecutionRequestException:

org.hibernate.hql.ast.QuerySyntaxException

原因:org.hibernate.QueryException:节点没有数据类型:org.hibernate.hql.internal.ast.tree.MethodNode

hibernate hsql得到错误节点没有数据类型:org.hibernate.hql.ast.tree.IdentNode

HQL 异常 (org.hibernate.dialect.Dialect$3)