Hello.
Hibernate generates wrong sql statement for updating version column when obtaining lock (LockMode.FORCE) for a subclass entity. It updates version column which is in root entity but put into where clause name of primary key column from subclass table and it is different that PK name of root table.
DDL
Code:
CREATE TABLE article_item
(
article_item_id integer NOT NULL,
ean ean,
"version" timestamp without time zone NOT NULL,
type_code character(1),
"number" character varying(40) NOT NULL,
not_available boolean NOT NULL,
CONSTRAINT pk_article_item PRIMARY KEY (article_item_id)
);
CREATE TABLE sale_company_article_item
(
sale_company_article_item_id integer NOT NULL,
sale_company_id integer NOT NULL,
article_ean_suffix integer,
sale_price numeric NOT NULL,
article_id integer NOT NULL,
CONSTRAINT pk_sale_company_article_item PRIMARY KEY (sale_company_article_item_id),
CONSTRAINT article_item_sale_company_article_item_id FOREIGN KEY (sale_company_article_item_id)
REFERENCES article_item (article_item_id) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT article_sale_company_article_item FOREIGN KEY (article_id)
REFERENCES article (article_id) ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT sale_company_sale_company_article_item FOREIGN KEY (sale_company_id)
REFERENCES sale_company (sale_company_id) ON UPDATE CASCADE ON DELETE RESTRICT
);
Mapping (I removed some associations for simplicity)
Code:
<hibernate-mapping package="com.uwiss.ned.domain.article">
<typedef class="com.uwiss.jenive.hibernate.type.StringEnumValueType" name="articleItemTypeEnum">
<param name="CLASS_NAME">com.uwiss.ned.domain.article.ArticleItem$Type</param>
</typedef>
<class name="ArticleItem" table="article_item">
<id name="id" column="article_item_id">
<generator class="org.hibernate.id.SequenceGenerator">
<param name="sequence">article_item_seq</param>
</generator>
</id>
<timestamp name="version"/>
<property name="ean"/>
<property name="number"/>
<property name="notAvailable" column="not_available" not-null="true"/>
<property name="type" column="type_code" type="articleItemTypeEnum" not-null="true"/>
<joined-subclass name="com.uwiss.ned.domain.salecompanyarticleitem.SaleCompanyArticleItem"
table="sale_company_article_item">
<key column="sale_company_article_item_id" not-null="true"/>
<property name="articleEanSuffix" column="article_ean_suffix"/>
<property name="salePrice" column="sale_price" not-null="true"/>
</joined-subclass>
</class>
</hibernate-mapping>
Wrong SQL statement
Code:
Hibernate:
update
article_item
set
version=?
where
sale_company_article_item_id=?
and version=?
17:46:32,199 WARN RMI TCP Connection(5)-10.4.0.37 JDBCExceptionReporter:logExceptions:100 - SQL Error: 0, SQLState: 42703
17:46:32,200 ERROR RMI TCP Connection(5)-10.4.0.37 JDBCExceptionReporter:logExceptions:101 - ERROR: column "sale_company_article_item_id" does not exist
Code which raises exception
Code:
...
SaleCompanyArticleItem articleItem = saleOrderline.getDeliveredSaleCompanyArticleItem();
...
session.lockEntity(articleItem, LockMode.FORCE);
...
Method generateVersionIncrementUpdateString() from AbstractEntityPersister uses method getIdentifierColumnNames() which overriden in JoinedSubclassEntityPersister and this method return PK name from subclass table.
Obviously workaround solution for this problem is giving the same name to PK fields in tables of hierarchy.