In my understanding the "table" attribute of the @JoinColumn annotation identifies in what table the join column resides. Hibernate (3.3.2.GA / Oracle) however does not seem to take note of that. Here is a simplified version of my problem mapping:
Code:
-- DDL (Oracle) :
CREATE TABLE demo_config
(
id NUMBER(19, 0) NOT NULL,
dtype VARCHAR2(31 CHAR) NOT NULL,
name VARCHAR2(255 CHAR) NOT NULL,
CONSTRAINT demo_config_PK PRIMARY KEY(id)
);
CREATE TABLE demo_provider
(
name VARCHAR2(255 CHAR) NOT NULL,
CONSTRAINT demo_provider_PK PRIMARY KEY (name)
);
CREATE TABLE demo_simple_config (
id NUMBER(19, 0) NOT NULL,
some_property VARCHAR2(255 CHAR) NOT NULL,
provider VARCHAR2(255 CHAR) NOT NULL,
CONSTRAINT demo_simple_config_PK PRIMARY KEY (id),
CONSTRAINT demo_simple_config_FK1 FOREIGN KEY(id)
REFERENCES demo_config ON DELETE CASCADE,
CONSTRAINT demo_simple_config_FK2 FOREIGN KEY(provider)
REFERENCES demo_provider ON DELETE CASCADE
);
Code:
// Java classes. Imports omitted for the sake of conciseness.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class DemoConfig
implements Serializable
{
private static final long serialVersionUID = 1L;
private Long id;
private String name;
@Id
@GeneratedValue
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
@Entity
public class DemoProvider
implements Serializable
{
private static final long serialVersionUID = 1L;
private String name;
protected DemoProvider()
{
}
@Id
protected String getName()
{
return name;
}
protected void setName(String name)
{)
this.name = name;
}
}
@Entity
@SecondaryTable(name = "demo_simple_config")
@Table(appliesTo = "demo_simple_config", fetch = SELECT)
public class DemoSimpleConfig
extends DemoConfig
implements Serializable
{
private static final long serialVersionUID = 1L;
private String someProperty;
private DemoProvider provider;
@Column(table = "demo_simple_config")
public String getSomeProperty()
{
return someProperty;
}
public void setSomeProperty(String someProperty)
{
this.someProperty = someProperty;
}
@ManyToOne(targetEntity = DemoProvider.class)
@JoinColumn(table = "demo_simple_config")
public DemoProvider getProvider()
{
return provider;
}
public void setProvider(DemoProvider provider)
{
this.provider = provider;
}
}
The problem occurs with mapping of the field DemoSimpleConfig.provider. If it is not mapped then Hibernate fetches DemoSimpleConfig objects correctly like this:
Code:
DEBUG -
select
democonfig0_.id as id18_0_,
democonfig0_.name as name18_0_,
democonfig0_.dtype as dtype18_0_
from
demo_config democonfig0_
where
democonfig0_.id=?
DEBUG -
select
democonfig_1_.some_property as some1_20_
from
demo_simple_config democonfig_1_
where
democonfig_1_.id=?
When DemoSimpleConfig.provider field is mapped as shown above though, Hibernate does not seem to honor the "table" attribute of @JoinColumn which is supposed to tell it to look for that field in the secondary table (joined with the table "demo_provider"). Instead Hibrenate looks for the field in the primary table and fails like this:
Code:
DEBUG -
select
democonfig0_.id as id18_1_,
democonfig0_.name as name18_1_,
democonfig0_.dtype as dtype18_1_,
demoprovid1_.name as name19_0_
from
demo_config democonfig0_
left outer join
demo_provider demoprovid1_
on democonfig0_1_.provider=demoprovid1_.name
where
democonfig0_.id=?
ERROR - ORA-00904: "DEMOCONFIG0_1_"."PROVIDER": invalid identifier
ERROR - data access error
java.sql.SQLException: ORA-00904: "DEMOCONFIG0_1_"."PROVIDER": invalid identifier
Can somebody please advise whether there is something wrong with this mapping or it really demonstrates a bug in Hibernate? If it is a bug then does anybody know of a workaround?