tags:

views:

383

answers:

1

I have following model,


@Entity
@Table(name = "user")
@PrimaryKeyJoinColumn(name="user_id")
@SecondaryTables({
@SecondaryTable(name = "user_personal_details", pkJoinColumns = {@PrimaryKeyJoinColumn(name = "user_id", referencedColumnName = "user_id")}),
@SecondaryTable(name = "user_address", pkJoinColumns = {@PrimaryKeyJoinColumn(name = "user_id", referencedColumnName = "user_id")}),
@SecondaryTable(name = "user_contact_info", pkJoinColumns = {@PrimaryKeyJoinColumn(name = "user_id", referencedColumnName = "user_id")}),
@SecondaryTable(name = "user_auth_info", pkJoinColumns = {@PrimaryKeyJoinColumn(name = "user_id", referencedColumnName = "user_id")})
})
public abstract class User extends Member implements IUser {
    @Column(table="user_personal_details")
    private UserPersonalDetails personalInfo;
    @Column(table="user_address")
    private Address address;
    @Column(table="user_contact_info")
    private UserContactDetails contactDetails;
    @Column(table="user_auth_info")
    private UserAuthInfo authInfo;
...
}

When I try to insert a subclass of User I get an error shown below

10641 [main] ERROR org.hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure:Table user_personal_details not found

Please shed some light on this behavior.

Class Definitions:-

ManagedObject Class



@Entity
@Table(name="managed_object")
@Inheritance(strategy=InheritanceType.JOINED)

public abstract class ManagedObject implements IManagedObject
{
    @Id
        @Column(name="mo_id", nullable=false, updatable=false)
        private String id;
    @Column(name="mo_name", nullable=false, updatable=true)
        private String name;
        @Column(name="mo_type", nullable=false, updatable=true)
    private String type;
        @Column(name="mo_additional_info", nullable=true, updatable=true)
    private String additionalInfo;
...
}

Member Class



@Entity
@Table(name="t_member")
@PrimaryKeyJoinColumn(name="member_id")
public abstract class Member extends ManagedObject implements IMember {

}

One of the Data/Info Class like UserPersonalDetails



@Embeddable
@Table
public class UserPersonalDetails extends InfoObject{
    private String firstName;
    private String middleName;
    private String lastName;
...
}

Update:

Added @Column(table="") annotation in UserPersonalDetails members and yes I do have @Embedded annotation in User class. I have encountered following exception:


4469 [main] ERROR org.hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: Table user_personal_details not found
A: 

You did not map other classes (like UserPersonalDetails) correctly.

They either need to be mapped as @Embedded or as true @ManyToOne (or, possibly, @OneToOne) associations.

The way it is right now you're trying to map an entire class (UserPersonalDetails) to a single column (personalInfo because you didn't specify name explicitly) in joined table (user_personal_details), which will not work.

Update (based on mappings posted to question)

You haven't updated your User class, I'm going to assume you've replaced the @Column declarations with @Embedded in it. Basically, what you need is:

// header annotations are the same as above
public abstract class User extends Member implements IUser {
  @Embedded
  private UserPersonalDetails personalInfo;
  // other components go here
  ...
}

@Embeddable
public class UserPersonalDetails extends InfoObject {
  @Column(table="user_personal_details")
  private String firstName;

  @Column(table="user_personal_details")
  private String middleName;

  @Column(table="user_personal_details")
  private String lastName;
  ...
}

As you can see, you need to declare the table your component's columns will be mapped to because by default they all go to the "main" table (e.g. the one your entity is mapped to). That can NOT be done using @Table annotation on embeddable - you need to do it via @Column as shown above or via @AttributeOverrides but the latter is messier.

ChssPly76
I don't think I can map with @ManyToOne/@OneToOne as classes like UserPersonalDetails are not entities,they are pure data classes. I have also tried suggested @Embedded annotation here are my observations - -I dont encounter any error-Tables for data classes ie. tables such as user_personal_details is getting created with user_id as primary key but no sign of other columns in that table-Table user has all those columns corresponding to attributes which are defined in data classes like UserPersonalDetails-When I save the User object UserPersonalDetails data gets stored in user table columns
Chetan
Perhaps you should make them entities; it seems rather strange to have model structure separated into multiple tables if there are no actual relationships. That's just my opinion, though - you can most certainly map them as embedded instead. It's hard to comment on your "observations" without seeing your mapping - if you can update your question to show mappings for your classes (user + any nested one should suffice) I'll take a look. From your description it seems you're not specifying "table" attribute on your nested columns - and you have to becase of your @SecondaryTable mappings.
ChssPly76
I want some separation between core entity information and other characteristics of that entity so I am trying to further break/classify information associated with that entity. I understand that by not doing so there wont be any effect on programming model as such.Currently I am actually embedding these pure info/data classes in entity table for now and moving ahead without getting stuck however I am kind of learning Hibernate so I just want to make sure that I learn Hibernate mapping techniques thoroughly. Anyway, thanks for your inputs. P.S: Please see the updated question.
Chetan
Please see updated question
Chetan
Well, is the table actually there in the database? If it exists and you've mapped it as @SecondaryTable on User it should work just fine.
ChssPly76
No the table is not there, I have a set following property in hibernate config file - <property name="hbm2ddl.auto">create-drop</property>. I thought Hibernate will create right schema.
Chetan
'create-drop' should be used for unit tests only; it assumes there's no schema to begin with and it will drop the schema after sessionFactory is destroyed. You should probably set it to `update` instead; however I suggest you get your mappings working first for **existing** schema without further complicating matters with auto-generation which you can add afterwards.
ChssPly76
Actually the truth is that there is no schema in place. It would have been better if Hibernate would have been able to generate it based on the mapping annotations provided. Are you suggesting that its not a good practice to ask Hibernate to generate the schema? Btw I am curious to know why is it that Hibernate is not able to generate user_personal_details table when mapping suggests that such a table should be there through @SecondaryTable annotation and when auto-generation is enabled?
Chetan
Hibernate is able to generate the schema provided everything's configured correctly. Clearly, you're having problems with that - I am therefore suggesting that you take it one step at a time in order to make troubleshooting easier. I'm guessing your mappings contain more than just classes you've posted above; it's possible you have an error in some other mapping that prevents Hibernate from successfully building session factory and thus generating the schema.
ChssPly76
Yes thats right I have few more classes in there but what baffles me is the fact that if I remove this particular stuff then other schema is getting generated properly..so though I thought about the possibility of this error being result of some other mappings I kind of discarded that possibility but now it seems that could be the reason..I will try to go with already present schema and check how it goes...
Chetan