-->
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.  [ 1 post ] 
Author Message
 Post subject: Using @SqlResultSetMapping to "eager fetch" @OneToOne props
PostPosted: Fri Nov 13, 2009 5:59 am 
Newbie

Joined: Mon Feb 20, 2006 9:23 am
Posts: 9
I'm using Hibernate annotations to execute a stored procedure in SQL server and I want to use @SqlResultSetMapping to have the results returned as a collection of entities.

What I'm trying to accomplish is have each member of the result set be a single instance of my Java class, with that classes properties that map to @OneToOne relationships populated by other Java objects hydrated from other columns returned by the stored procedure. I want to do this in one round-trip (i.e. I don't want Hibernate going back to SQL to fill in any missing properties).

My simplified schema (excuse the loose syntax) is very straightforward

Code:
TABLE A {
  PRIMARY KEY BIGINT id
  NVARCHAR(30) name
}

TABLE B {
  PRIMARY KEY BIGINT id FOREIGN KEY REFERENCES (A,Id)
  NVARCHAR(30) name
  NVARCHAR(20) type
}


My Java mapping is

Code:
@Entity
class A {
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  long id;
  String name;

  @OneToOne(mappedBy="a")
  B b;
}

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="Type",discriminatorType=DiscriminatorType.STRING)   
@GenericGenerator(name="JOIN_GENERATOR",strategy="foreign",parameters={@Parameter(name="property",value="a")})
abstract class B {
  @Id
  @GeneratedValue(generator="JOIN_GENERATOR")
  long id;
  String name;

  @OneToOne
  @PrimaryKeyJoinColumn
   A  a;
}

@Entity
@DiscriminatorValue("B1")
class B1 extends B { }

@Entity
@DiscriminatorValue("B2")
class B2 extends B { }


i.e. I have a Class A that has a One-to-one relationship to a class B, the latter of which is mapped to
a single-table inheritance hierarchy realised by two concrete types B1 and B2.

My SQL Query looks something like this

Code:
SELECT  TA.id id, TA.name name, TB.id B_id, TB.type B_type, TB.name B_name
FROM A TA LEFT OUTER JOIN B TB ON TA.id = TB.id


i.e. there is enough information returned in the query for Hibernate to hydrate an instance of A with an appropriate reference to a hydrated instance of B1 or B2.

I've tried numerous @SqlResultSetMapping strategies without complete success.

The first was to declare each class as an entity e.g. something like the following (note that implicit column-property binding is used for A but is not used for B because otherwise there would be a clash as both tables have id and name columns).

Code:
@SqlResultSetMapping(
  name="myMapping",
  entities={
    @EntityResult(entityClass=A.class),
    @EntityResult(entityClass=B.class,
      fields={
        @FieldResult(name="id",column="B_id"),
        @FieldResult(name="name",column="B_name")
      },
      @discriminatorColumn("B_type")
  }
)


- but this returned each result as a tuple <A,B> rather than just A.

My second attempt was to attempt to remove the top-level presence of B from each result by not declaring it as an entity in its own right but referencing the properties by "." notation i.e.

Code:
  entities={
    @EntityResult(entityClass=A.class,
      fields={
        @FieldResult(name="b.id",column="B_id"),
        @FieldResult(name="b.name",column="B_name")
      }
  }
)


However there are two problems with this: the first is that I've lost the ability to specify the discriminatorColumn for B as there is no @EntityResult to hang it off. I can't see how Hibernate is going to know how to rehydrate the correct subclass (B1 or B2) as it won't know which column in the result set represents the discriminator.

The second problem is more immediate; I get the following error running hbm2ddl on my annotated java classes:

Code:
[hibernatetool] org.hibernate.MappingException: dotted notation reference neither a component nor a many/one to one
[hibernatetool] java.lang.ClassCastException: org.hibernate.mapping.SimpleValue


Is what I'm attempting not possible? I can just about live with dealing with the mapping that returns tuples <A,B> as long as A's inner references to B are correct and Hibernate doesn't do any more roundtrips under the covers to populate it. But I wondered if there was a way of using @SqlResultSetMapping to only return properly hydrated instances of A with their b properties "eagerly fetched".


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

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.