Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: field mapped to discriminator column not getting set
PostPosted: Tue Dec 12, 2006 2:08 pm 
Beginner
Beginner

Joined: Tue Nov 14, 2006 4:11 pm
Posts: 23
Hibernate: 3.2.1.ga / Annotations: 3.2.1.GA / EntityManager: 3.2.1.GA

I'm using a JOINED inheritence strategy with a discriminator column. The superclass also has a field mapped to the discriminator column. When I try to persist the subclass, I get a PropertyValueException:
Code:
not-null property references a null or transient value: edu.jhuapl.ermp.model.entities.Task.aplEntityType
on the field mapped to the discriminator column. AFAICT, this means the field is not getting set with the discriminator value as it should. The classes are:

Code:
@Entity
@Table(name="APL_ENTITY", schema="ERMPMGR")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="apl_entity_type_code", discriminatorType=DiscriminatorType.STRING)
public abstract class APLEntity {

    @Column(name="APL_ENTITY_TYPE_CODE", nullable=false)
    private APLEntityType aplEntityType;
   
    @Id
    @Column(name="APL_ENTITY_SEQ_NUM", nullable=false)
    private Long id;
    ...
   
   
@Entity
@Table(name="subtask", schema="fpbadmin")
@DiscriminatorValue("TASK")
public class Task extends APLEntity {
   
    @Column(name="SUBTASK_ID")
    private String taskID;
    ...


I've also tried it with a
Code:
@PrimaryKeyJoinColumn(name="apl_entity_seq_num")
on the Task class (which shouldn't be required since both tables use same column name--should be applied by default), but still the same problem.

I've looked over the hibernate unit tests for this type of mapping and aside from the mapping to the discriminator column, they seem similar. Any ideas anyone?

TIA, Clark


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 17, 2006 5:08 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7179
Location: Atlanta, USA
make the property read only insertable=false, updatable=false

note that Hibernate has the notion of @Generated properties, have a look at the ref doc

_________________
Emmanuel
Check Hibernate Search in Action out


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 19, 2006 7:02 pm 
Beginner
Beginner

Joined: Tue Nov 14, 2006 4:11 pm
Posts: 23
I've tried the settings you recommended along with some other changes:

Code:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="apl_entity_type_code", discriminatorType=DiscriminatorType.STRING)
@Table(name="apl_entity", schema="ermpmgr")
public abstract class APLEntity 
    implements InternalContactAssignable, ExternalContactAssignable, Authorizable {

    @ManyToOne
    @JoinColumn(name="APL_ENTITY_TYPE_CODE", nullable=false, insertable=false, updatable=false)
    private APLEntityType aplEntityType;
   
    @Id
    @Column(name="APL_ENTITY_SEQ_NUM", nullable=false)
    private Long id;
    ...

@Entity
@DiscriminatorValue("TASK")
@Table(name="subtask", schema="fpbadmin")
public class Task extends APLEntity {
    ...


and now I get a different error when I try to commit a newly persisted object:
Code:
ORA-01400: cannot insert NULL into ("ERMPMGR"."APL_ENTITY"."APL_ENTITY_TYPE_CODE")


This is supposed to be set as the discriminator column. What's curious is that I can completely remove the @DiscriminatorColumn from APLEntity and I get the exact same error. What doesn't Hibernate like about the discriminator settings I'm using?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 20, 2006 7:45 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7179
Location: Atlanta, USA
Weird, I think this might be a bug in core, can you try and implement in in hbm file. If it fails, post it to JIRA, we'll have to fix it.

_________________
Emmanuel
Check Hibernate Search in Action out


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 22, 2006 3:52 pm 
Beginner
Beginner

Joined: Tue Nov 14, 2006 4:11 pm
Posts: 23
This is a bit of a long shot, since it seems pretty fundamental, but here goes:

In stepping through the debugger, when the JoinedSubclassEntityPersister goes to build the static inserts for the entities in question, via the method
Code:
AbstractEntityPersister.generateInsertString(boolean, boolean[], int)

what ends up getting called is
Code:
AbstractEntityPersister.addDiscriminatorToInsert(Insert)
which is an empty do-nothing method. However, the SingleTableEntityPersister provides an implementation for this method.

Is there any chance that someone simply forgot to override addDiscriminatorToInsert in JoinedSubclassEntityPersister? I realize perhaps something more complex is going on (especially since UnionSubclassEntityPersister doesn't override it either) and the discriminator is perhaps supposed to get added somewhere else, but seems like it could be the problem.

In the meantime, I'll work up the example using an hbm file.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 27, 2006 8:17 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7179
Location: Atlanta, USA
ah
Contrary to inferior ORM implementations, Hibernate does not need a discriminator column when using JOINED (table per subclass), Hibernate Annotations completely ignores the discriminator column

_________________
Emmanuel
Check Hibernate Search in Action out


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 27, 2006 11:36 am 
Beginner
Beginner

Joined: Tue Nov 14, 2006 4:11 pm
Posts: 23
Hmmm. Seems like it is a bit of a gray area w/ regard to the spec. Page 157 of the spec says:
Quote:
The DiscriminatorColumn annotation is used to define the discriminator column for SINGLE_TABLE and JOINED mapping strategies.

And the book Pro EJB 3 says on page 250:
Quote:
Some vendors offer implementations of joined inheritance without the use of a discriminator column. Discriminator columns should be used if portability is required

My impression (obviously incorrect) was that Hibernate would honor the use of a discriminator column even thought it doesn't need to use it, based on the above. In my case, it's a legacy requirement (it was mapped using a discriminator column using toplink--and other parts of the system are now relying on the discriminator column).

Reasonable people may disagree, but I view this as a bug. I'm guessing you see this as a feature request--unless I've managed to convince you. How should I proceed to try to get this addressed?

And are there any workarounds you can think of? I thought about trying to @Generated and UserType but didn't didn't see a way (but I'm a newbie).

Thanks, Clark


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 27, 2006 12:22 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7179
Location: Atlanta, USA
JOINED (wo discriminator) is the normalized model, we will not workaround other product limitations :-)
A user type should work fine, nullSafeGet retrieving the discriminator value from the object type and nullSafeSet setting the discr value from the object type. You 'll have to use ParameterizedType to make your user type configurable.

Hibernate can still guess the object type from the joins.

_________________
Emmanuel
Check Hibernate Search in Action out


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 27, 2006 1:33 pm 
Beginner
Beginner

Joined: Tue Nov 14, 2006 4:11 pm
Posts: 23
As I said, reasonable people will disagree on this--and I disagree :-)

If I were to submit a patch that implemented it, would it be accepted (assuming it worked ;-)? I don't want to waste my time if it would be categorically rejected.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 28, 2006 10:47 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1812
Location: Austin, TX
You disagree because that is how your schema is designed. Trust me, if you step back and look at it objectively, this makes no sense (zero, nada, none).

This design itself is not invalid. It is valid from the perspective that it is a performance enhancement to add the discriminator such that the joins do not need to be performed up front. Instead we can read from the base table, inspect the discriminator value and decide which additional tables to read from there... But this is not what you asked for. And actually Hibernate can already basically do what I just described using a combination of <subclass/> and <join/>.

So yes, what you actually suggest (simply handling the discriminator on insert) will be categorically rejected. If you really want that, you can supply a custom EntityPersister implementation that overrides this method.

If you want to look at the other approach where the hierarchy is actually discriminated based on this discriminator column, assuming you have this mapping:
Code:
<class name="RootClass" table="ROOT_CLASS" ...>
    ...
    <joined-subclass name="SubClass" table="SUB_CLASS">
        <key column="ROOT_ID"/>
        ...
    </joined-subclass>
</class>


the basic usage would be to change the above to:
Code:
<class name="RootClass" table="ROOT_CLASS" ...>
    ...
    <discriminator column="YOUR_DISCRIM_COLUMN"/>
    ...
    <subclass name="SubClass" discriminator-value="sub">
        <join table="SUB_CLASS" fetch="select">
            <key column="ROOT_ID"/>
            ...
        </join>
    </subclass>
</class>


This does however impose the limitations of the <join/> mapping construct on this hierarchy mapping; namely collections would not be allowed within the <join/>...[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 01, 2007 11:57 am 
Beginner
Beginner

Joined: Tue Nov 14, 2006 4:11 pm
Posts: 23
Actually, no. I disagreed because what I read (two books and the spec) led me to think that the discriminator column would be honored, even if the JPA implementation didn't require it. Perhaps I'm not being objective here.

For our particular situation, it is how our prior Toplink mapping was done (for better or for worse), and now we have other systems that are relying on it. So in this sense it is a legacy requirement.

I'll take a look at your suggested mapping and see if it will help in this case.

Thanks, Clark.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.