I've stumbled across a configuration which generates invalid SQL, and I think it should not.
Code:
<hibernate-mapping package="test" schema="test">
<class name="Car" table="Car" lazy="false">
<id name="id" column="id" type="long" unsaved-value="0" >
<generator class="native"/>
</id>
</class>
<class name="Parent" table="Parent">
<id name="id" column="id" type="long" unsaved-value="0" >
<generator class="native"/>
</id>
<discriminator column="parentType" />
<subclass name="Father" discriminator-value="FATHER">
<join table="Father" fetch="select">
<key column="id" />
<many-to-one name="car" column="carId" />
</join>
</subclass>
</class>
</hibernate-mapping>
There's nothing fancy about anything in my setup, and the classes are dumb beans containing only the properties shown.
As a test, I insert a new Car, then create a new Father, set the Car on the Father, and insert it. Then I try to retrieve the Father using the generated Id:
Code:
Car car = new Car();
session.saveOrUpdate(car);
Father newFather = new Father();
newFather.setCar(car);
session.saveOrUpdate(newFather);
session.evict(car);
session.evict(newFather);
Parent retrievedParent = (Parent) session.load(Parent.class, newFather.getId());
It generates the following output:
Quote:
Hibernate: insert into test.Car values ( )
Hibernate: insert into test.Parent (parentType) values ('FATHER')
Hibernate: insert into test.Father (carId, id) values (?, ?)
Hibernate: select parent0_.id as id30_1_, parent0_.parentType as parentType30_1_, car1_.id as id29_0_ from test.Parent parent0_ left outer join test.Car car1_ on parent0_1_.carId=car1_.id where parent0_.id=?
<snip>
org.hibernate.exception.SQLGrammarException: could not load an entity: [test.Parent#10]
<snip>
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'parent0_1_.carId' in 'on clause'
What I expect it to do is to join against Parent on id, then join against Father AND Car on id. Instead, it joins Car and Parent using the carId column which is only located on Father.
I can do several things to fix this issue:
1) Add fetch="select" to the many-to-one mapping for car on Father
2) Remove lazy="false" on Car
3) Remove fetch="select" on Father
I believe this is a bug. If the mapping is invalid, then it should fail during parse time, not run time.
I'm using hibernate 3.3.2 and MySql. For reference, here is the database schema for the test:
Code:
CREATE TABLE Parent (
id int(11) not null auto_increment,
parentType varchar(20) not null,
PRIMARY KEY (id)
) ENGINE=InnoDB;
CREATE TABLE Car (
id int(11) not null auto_increment,
PRIMARY KEY (id)
) ENGINE=InnoDB;
CREATE TABLE Father (
id int(11) not null,
carId int(11) not null,
PRIMARY KEY (id),
CONSTRAINT parentIdFK FOREIGN KEY (id) REFERENCES Parent (id),
CONSTRAINT carIdFK FOREIGN KEY (carId) REFERENCES Car (id)
) ENGINE=InnoDB;