I'm seeing strange behaviour when using PostgreSQL in a Hibernate/JPA environment with a single table inheritance hierarchy.
Firstly my environment:
- PostgreSQL 8.3
- Spring 2.5.6SEC01
- Hibernate-entitymanager 3.4.0.GA (installed from Glassfish update tool)
- Hibernate-distribution 3.3.1.GA (installed from Glassfish update tool)
- Glassfish V2
- Mac OS X 10.5.x
I'm having an issue when using a GenerationType
of IDENTITY
with a single table inheritance hierarchy.
Here are my two entities:
Parent.java
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="generation", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("Parent")
public class Parent implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Child.java
@Entity
@DiscriminatorValue("Child")
public class Child extends Parent {
private String babyName;
/**
* @return the babyName
*/
public String getBabyName() {
return babyName;
}
/**
* @param babyName the babyName to set
*/
public void setBabyName(String babyName) {
this.babyName = babyName;
}
}
DDL
create table Parent (generation varchar(31) not null
,id bigserial not null
,babyName varchar(255)
,primary key (id)
);
If I try to insert a new Parent I get an error:
org.postgresql.util.PSQLException: Bad value for type long : Parent
I turned up the logging to TRACE and this is the output:
TRACE TransactionSynchronizationManager - Bound value [org.springframework.orm.jpa.EntityManagerHolder@485e0366] for key [com.sun.enterprise.util.EntityManagerFactoryWrapper@a6e312b] to thread [httpSSLWorkerThread-8080-0] Hibernate: insert into Parent (generation) values ('Parent') SQL Error: 0, SQLState: 22003 Bad value for type long : Parent TRACE TransactionInterceptor - Completing transaction for [com.xxx.yyy.service.MoveService.saveHuman] after exception: javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not insert: [com.xxx.yyy.temp.Parent] TRACE RuleBasedTransactionAttribute - Applying rules to determine whether transaction should rollback on javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not insert: [com.xxx.yyy.temp.Parent]
If I change the discriminator value to be something that parses as a long e.g. 123
the insert succeeds. However Hibernate seems to think this discriminator value is the id. So the following code:
Parent p = new Parent();
service.saveHuman(p);
add(new Label("p", "p id is" + p.getId()));
Shows the id as 123
rather than the primary key value which is 1.
If I change the generation type to AUTO
a single sequence is created and the insert seems to work ok. If I change it to SEQUENCE
and declare the sequence with a class-level annotation again it works. However according to the documentation I have read PostgreSQL supports both generation types.
I also tried the exact same code and switched out the database with MySQL 5.0.51b. This seems to function fine.
So is this a bug in my code, the dialect, Hibernate, or the PostgreSQL JDBC driver? Any ideas how I can narrow down the problem? Anyone able to re-produce this issue as I have tried to search and haven't seen this exact problem yet.
Note: I've also asked the question on the Hibernate Forums. Naturally I will feedback any responses to both sites.