-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: polymorphic associations do not work with annotations but wo
PostPosted: Thu Jan 15, 2009 4:36 pm 
Newbie

Joined: Fri Aug 10, 2007 2:04 am
Posts: 7
Hibernate version:
hibernate 3.3
hibernate annotations 3.4

domain model diagram
http://forum.springframework.org/attach ... 1232047492

I am using Spring 2.5.x and Hibernate3.3.
I have attached my model diagram (model.jpg).
In short, Transaction-to-Risk is a many-to-many association
for which we have used a intermediary Transaction_Risk join table (which has two columns Transaction_id and Risk_id)

Transaction <-> Transaction_Risk (jointable) <-> BaseRisk

we are trying to access subclasses of BaseRisk polymorphically,

Code:

Code:
for (Iterator iter = t.getRisks().iterator(); iter.hasNext();) {
         BaseRisk element = (BaseRisk) iter.next();

but before we do this above (very basic) for loop does not work for us if we use annotations to do the hibernate mapping but works fine if we use xml mapping. Theoretically ofcourse its supposed to work both ways.

BaseRisk hierarchy is mapped using single-table-per-class-hierarchy.
here's the xml mapping (it works)
Code:

Code:
<class name="BaseRisk" table="risk">
      
      <discriminator column="risk_type" type="string" />
      <join table="TRANSACTION_RISK" inverse="true" optional="false">
         <key column="RISK_ID" />
         <many-to-one name="transaction" column="TRANSACTION_ID"/>
      </join>
      
      <subclass name="RiskPPV" extends="BaseRisk" discriminator-value="RISK_PPV">
         <many-to-one name="vehiclePPV" column="vehicle_id" access="field" cascade="all" />
      </subclass>
      
      <subclass name="RiskOther" extends="BaseRisk"></subclass>
      <subclass name="RiskPUF" discriminator-value="RISK_PUF" extends="RiskOther">
         <many-to-one name="vehiclePUF" column="vehicle_id" access="field" cascade="all" />
      </subclass>
</class>



<class name="Transaction" table="TRANSACTION">
      <set name="risks" table="TRANSACTION_RISK" cascade="all">
         <key column="TRANSACTION_ID" />
         <many-to-many column="RISK_ID" class="BaseRisk" />
      </set>
</class>

It looked like following in annoations

Here are the BaseRisk and Transaction classes
Code:

Code:
@Entity
@Table(name = "RISK")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "RISK_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class BaseRisk {

@ManyToOne(cascade = CascadeType.ALL)
   @JoinTable(name = "TRANSACTION_RISK", joinColumns = @JoinColumn(name = "RISK_ID"), inverseJoinColumns = @JoinColumn(name = "TRANSACTION_ID"))
   private Transaction transaction;
   
   
   getters and setters ...
}


@Entity
@Table(name = "TRANSACTION")
public class Transaction extends BaseModel
{
@OneToMany (cascade = CascadeType.ALL)
   @JoinTable(name="TRANSACTION_RISK",
            joinColumns=@JoinColumn(name = "TRANSACTION_ID"),
            inverseJoinColumns=@JoinColumn(name="RISK_ID")
   )
   private Set<BaseRisk> allBaseRisks = new HashSet<BaseRisk>() ;

Here's the rest of the risk Hierarchy

Code:

public abstract class RiskOther extends BaseRisk {

....

}

@Entity
@DiscriminatorValue("RISK_PUF")
public class RiskPuf extends RiskOther {
   @OneToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "VEHICLE_ID")
   private VehiclePuf vehiclePuf;


   public VehiclePuf getVehiclePuf() {
      return vehiclePuf;
   }

   public void setVehiclePuf(VehiclePuf vehiclePuf) {
      this.vehiclePuf = vehiclePuf;
   }
}

@Entity
@DiscriminatorValue("RISK_PPV_ONT")
public class RiskPPV extends BaseRisk {
...
}



As mentioned above, with the above shown annotation based mapping, when I run the test to load allBaserisks and iterate through them using a for loop
Code:

Code:
Policy policy = (Policy)sessionFactory.getCurrentSession().load(Policy.class, new Long(2971));
Assert.assertNotNull(policy.getAllBaseRisks());
for (Iterator iter = policy.getAllRisks().iterator(); iter.hasNext();) {
         BaseRisk element = (BaseRisk) iter.next();

I get the exception
Code:

Code:
org.hibernate.PropertyAccessException: could not set a field value by reflection setter of org.sample.model.RiskPUF.vehiclePuf
at
org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:81)


Any help will be much appreciated..


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 16, 2009 12:23 pm 
Newbie

Joined: Fri Aug 10, 2007 2:04 am
Posts: 7
still stuck with this issue, anybody... /?
Thanks.


Top
 Profile  
 
 Post subject: Re: polymorphic associations do not work with annotations but wo
PostPosted: Wed Sep 30, 2009 3:28 am 
Newbie

Joined: Wed Sep 30, 2009 3:21 am
Posts: 3
We are stuck with the same issue on a similar setup. We found out that Hibernate is trying to instantiate the wrong type, that is why it is going wrong. I will post our setup too and hope that someone reacts.


Top
 Profile  
 
 Post subject: Re: polymorphic associations do not work with annotations but wo
PostPosted: Wed Sep 30, 2009 4:25 am 
Newbie

Joined: Wed Sep 30, 2009 3:21 am
Posts: 3
Our setup (same spring and hibernate versions as above):

Two abstract classes:
A and B
Code:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@Table(name = "A")
public abstract class A implements Comparable<A> {
    @Id
    @Column(name = "ID")
    @SequenceGenerator(name = "a_id_seq_name", sequenceName = "a_id_seq", initialValue = 1000)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "a_id_seq_name")
    protected Long id;

and
Code:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@Table(name="B")
public abstract class B implements Comparable<B>{
    @Id@Column(name="ID")@SequenceGenerator(name = "b_id_seq_name", sequenceName = "b_id_seq", initialValue = 1000)@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="b_id_seq_name")
    protected Long id;
}



A has two subclasses A1 and A2, So does B: B1 and B2. Both Table per class hierarchy
A1 has a one-to-one relationship with B1:
Code:
@Entity@DiscriminatorValue("A1")
public class A1 extends A{
    @OneToOne(mappedBy = "a1", cascade = {CascadeType.ALL})
    private B1 b1;
}

Code:
@Entity@DiscriminatorValue("B1")
public class B1 extends B{
    @OneToOne(targetEntity = A1.class) @JoinColumn(name = "A_ID", nullable = false)
    private A1 a1;
    // add an attribute to get the same error as the user above
    @Column(name = "attribute", nullable = false)
    private Double attribute;

A2 has a one-to-many with B2:
Code:
@Entity@DiscriminatorValue("A2")
public class A2 extends A{
    @OneToMany(mappedBy = "a2", cascade = {CascadeType.ALL})
    @org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<B2> b2s = new TreeSet<B2>();

Code:
@Entity@DiscriminatorValue("B2")
public class B2 extends B{
    @ManyToOne(targetEntity = A2.class) @JoinColumn(name = "A_ID", nullable = false)
    private A2 a2;


The key here is that both B1 and B2 are using the same column 'A_ID' to point to their relation with A.

When using hibernate to load an object of type B1, it does so correctly, but it loads the property a1 in its second pass as an object of type A2. When it tries to set the property a1 as an object of type A2 you get the PropertyAccessException: could not set a field value by reflection setter issue.
We found that out while debugging with log4j.logger.org.hibernate=TRACE and stepping through the hibernate code.

The temporary work-around is as you say to put the mappings of B in xml, that works correctly:
Code:
<class name="B" table="B">
        <id name="id" column="ID" type="long">
            <generator class="sequence">
                <param name="sequence">b_id_seq</param>
            </generator>
        </id>
        <discriminator column="TYPE" type="string" not-null="true" />
</class>

Code:
<subclass name="B1" extends="B" discriminator-value="B1">
        <many-to-one
                name="a1"
                lazy="false"
                column="A_ID"
                class="A1"/>
        <property name="attribute" type="java.lang.Double" column="attribute"/>
    </subclass>

Code:
<subclass name="B2" extends="B" discriminator-value="B2">
        <many-to-one
                name="a2"
                lazy="false"
                column="A_ID"
                class="A2"/>
    </subclass>


This should be filed as a bug imho. Or are we missing something?

Thanx for your time,
Rob.


Top
 Profile  
 
 Post subject: Re: polymorphic associations do not work with annotations but wo
PostPosted: Thu Oct 08, 2009 10:26 am 
Newbie

Joined: Wed Sep 30, 2009 3:21 am
Posts: 3
anybody any idea?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.