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.  [ 6 posts ] 
Author Message
 Post subject: Problem with two optional ManyToOne mappings
PostPosted: Fri Feb 23, 2007 12:33 am 
Newbie

Joined: Fri Feb 23, 2007 12:04 am
Posts: 3
I'm having trouble when I try to persist objects of a class referencing two other persistence classes, either of which is always null.

The class Counseling (a scheduled event for a user to either talk to a specific customer or do some other tasks) is referencing, as ManyToOne, both a Candidate (customer) and a Spacer (arbitrary task). However only one of these references will ever exist, the other being null.

These are the involved classes:


@Entity
public class Counseling implements Serializable, Comparable<Counseling>{

private Long id;
private AppUser consultant = null;
private Candidate candidate = null;
private Spacer spacer = null;
private Date scheduledDT = null;
private Boolean seen = false;
private Date recordCreated = null;
private Date updated = null;

public Counseling() {

}

public Counseling(Candidate candidate) {
this.candidate = candidate;
}

public Counseling(Spacer spacer) {
this.spacer = spacer;
}

public Counseling(AppUser consultant, Candidate candidate, Date scheduledDT) {
this.consultant = consultant;
this.candidate = candidate;
this.scheduledDT = scheduledDT;
}

public Counseling(AppUser consultant, Candidate candidate, DateMidnight dayBeingScheduled, TimeOfDay startTimeOfDay) {
this.consultant = consultant;
this.candidate = candidate;
this.setScheduledDT(dayBeingScheduled, startTimeOfDay);
}

public Counseling(AppUser consultant, Spacer spacer, Date scheduledDT) {
this.consultant = consultant;
this.spacer = spacer;
this.scheduledDT = scheduledDT;
}

public Counseling(AppUser consultant, Spacer spacer, DateMidnight dayBeingScheduled, TimeOfDay startTimeOfDay) {
this.consultant = consultant;
this.spacer = spacer;
this.setScheduledDT(dayBeingScheduled, startTimeOfDay);
}


@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;

}
public void setId(Long id) {
this.id = id;
}


@ManyToOne
@JoinColumn(name = "candidate_id", nullable=true )
public Candidate getCandidate() {
return candidate;
}

public void setCandidate(Candidate candidate) {
this.candidate = candidate;
if(candidate!=null) this.spacer = null;
}

@ManyToOne
@JoinColumn(name = "spacer_id", nullable=true )
public Spacer getSpacer() {
return spacer;
}

public void setSpacer(Spacer spacer) {
this.spacer = spacer;
if(spacer!=null) this.candidate = null;
}

@ManyToOne
@JoinColumn(name = "appuser_id" )
public AppUser getConsultant() {
return consultant;
}

public void setConsultant(AppUser consultant) {
this.consultant = consultant;
}

@Basic(optional=false)
public Date getScheduledDT() {
return scheduledDT;
}

public void setScheduledDT(Date scheduledDT) {
this.scheduledDT = scheduledDT;
}

@Basic(optional=false)
public Boolean getSeen() {
return seen;
}

public void setSeen(Boolean seen) {
this.seen = seen;
}
}


@Entity
public class Candidate implements Serializable{

private Long id;

private String wtcId = null;

private String firstName = null;
private String lastName = null;
......

public Candidate() {

}


@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

.....

}



@Entity
public class Spacer {
private Long id;
private String description;
......


public Spacer() {

}

public Spacer(String description, int category) {
super();
this.description = description;
this.category = category;
}

@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

......
}


When I create a new Counseling object with either only a Spacer or only a Candidate and try to persist it, I always get the following Exception:


org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of persistence.Spacer.id
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:171)
at org.hibernate.tuple.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:176)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:3257)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:2983)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:181)
at org.hibernate.engine.ForeignKeys$Nullifier.isNullifiable(ForeignKeys.java:137)
at org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:69)
at org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:47)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:263)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:167)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:114)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:559)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:547)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:543)
at persistence.DbInterface.storeInDb(DbInterface.java:50)
at com.idatso.gui.ListitemDropListener.onEvent(ListitemDropListener.java:157)
at org.zkoss.zk.ui.impl.EventProcessingThread.process1(EventProcessingThread.java:483)
at org.zkoss.zk.ui.impl.EventProcessingThread.process0(EventProcessingThread.java:454)
at org.zkoss.zk.ui.impl.EventProcessingThread.run(EventProcessingThread.java:360)
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:145)
... 23 more



Can a ManyToOne foreign key relation never be optional/null as I always believed or have I made another fundamental mistake here?

I'm using Hibernate / Hib. Annotations 3.2.1 and Postgres 8.0.7

Needless to say I'm fairly new to Hibernate, so any help would really be most welcome. Thanks in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 23, 2007 3:12 am 
Expert
Expert

Joined: Tue Jan 30, 2007 12:45 am
Posts: 283
Location: India
Hi andiklein

yes ManyToOne can be null means that in associated table its ID can be null by using not null ="true"

_________________
Dharmendra Pandey


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 23, 2007 3:13 am 
Expert
Expert

Joined: Tue Jan 30, 2007 12:45 am
Posts: 283
Location: India
Sorry not null="false"

_________________
Dharmendra Pandey


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 25, 2007 11:07 pm 
Newbie

Joined: Fri Feb 23, 2007 12:04 am
Posts: 3
Did I get this right? You recommend to mark the id fields in both Candidate and Spacer as not null = false

I do not know of any annotation to do this.
All I can find is @org.hibernate.validator.NotNull and @Id does not have any not-null parameter either.

So far I was under the impression that a ManyToOne reference is generally optional unless specifically marked as "not null".

What confuses me most is the IllegalArgumentException with the message "object is not an instance of declaring class".

In my test scenario I first create a new Spacer instance and persist it, after which I can also output its Long id by calling getId()

Subsequently I create a new Counseling object, set some of its values, including a reference to the Spacer, leaving the candidate reference on null.

When trying to persist it however I end up with the same old error
"org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of persistence.Spacer.id"


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 25, 2007 11:38 pm 
Expert
Expert

Joined: Tue Jan 30, 2007 12:45 am
Posts: 283
Location: India
Hi andiklein,

many to one tag would be like this

<many-to-one class="XYZ" column="XYZ_XYZ" name="xyx" not-null="false" />

For the annotation i have no idea

_________________
Dharmendra Pandey


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 26, 2007 1:21 am 
Newbie

Joined: Fri Feb 23, 2007 12:04 am
Posts: 3
Thanks Dharmendra

Unfortunately the nullability of the constraint, which, all along, I had set via the nullable parameter of my JoinColumn annotations, as seen below, does not seem to be the cure.

Code:
@ManyToOne
@JoinColumn(name = "candidate_id", nullable=true )
    public Candidate getCandidate() {
        return candidate;
    }


I used the same annotations for the other Many-To-One constraint Spacer.

The documentation for the PropertyAccessException lists several possible reasons, including

    * failure of a security check
    * an exception occurring inside the getter or setter method
    * a nullable database column was mapped to a primitive-type property
    * the Hibernate type was not castable to the property type (or vice-versa)

I cannot see any of these applying in my case however. All Ids are auto-generated (Postgres increment sequence) non-primitive Longs.

The getter in question, persistence.Spacer.getId() does not require any arguments, and why should it.

Code:
@Id @GeneratedValue(strategy=GenerationType.AUTO)
    public Long getId() {
        return id;
    }


So the key must be to figure out why an IllegalArgumentException is occurring when Hibernate calls it.

Might there be a problem with the key generation strategy (GenerationType.AUTO)? This has never made any trouble before and the same Postgres sequence is used for all other DB operations, e.g. the persistence of my Spacer instance in the first step.


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