Is it bad practice to use DiscriminatorFormula for migration of Hibernate databases?
I have an application using Hibernate for data persistence, with Spring on top (for good measure). Until recently, there was one persistent class in the application, A:
@Entity
public class A {
@Id
@Column(unique = true, nullable = false, updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
public String name;
}
I have since added a subclass of A, called B:
@Entity
public class B extends A {
public String description;
}
After adding B, I could now not load A's. The following exception was thrown:
class org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException :: Object with id: 1 was not of the specified subclass: A (Discriminator: null); nested exception is org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: A (Discriminator: null)
I added the following annotation and property to B, and it see开发者_运维百科ms to have solved the problem. Is this the right way to solve the issue?
...
@DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'A' ELSE dtype END)")
public class A {
private String dtype = this.getClass().getSimpleName();
...
(...) Until recently, there was one persistent class in the application, A:
With the following database representation:
ID NAME
-- ----
1 foo
2 bar
I have since added a subclass of A, called B (...)
And you didn't specify the Inheritance
annotation so the SINGLE_TABLE
mapping strategy is used. And In this strategy, all the classes in a hierarchy are mapped to a single table. The table has a column that serves as a “discriminator column”, that is, a column whose value identifies the specific subclass to which the instance that is represented by the row belongs.
The table then became:
ID NAME DTYPE
-- ---- -----
1 foo NULL
2 bar NULL
Where DTYPE is the default name of column to be used for the discriminator.
After adding B, I could now not load A's. The following exception was thrown (...)
Indeed, because existing values have a null value in the discriminator column, the provider doesn't know what subclass to instantiate.
I added the following annotation and property to B, and it seems to have solved the problem. Is this the right way to solve the issue?
That's one way but it is intrusive (your entities shouldn't be aware of the dtype
column) and Hibernate specific. In other words, it's a hack.
For me, the "right" way to solve this would be to update the DTYPE
column of existing A records to set the value to 'A'
(with Hibernate, the value defaults to the entity name):
UPDATE A SET DTYPE='A' WHERE DTYPE=NULL
This way, Hibernate would be able to load them properly.
精彩评论