-->
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: Many to Many relationship annotations
PostPosted: Mon Jul 28, 2008 12:13 pm 
Newbie

Joined: Fri Jul 25, 2008 10:40 am
Posts: 3
I am having issues with managing a Many to Many relationship. I have a user_address table which is comprised of the user and address class primary keys.

Below is the pertinent information:

Hibernate version:
3.2 and Annotations

Mapping documents:
package com.xxxx.users;

import org.hibernate.annotations.Cascade;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;

@Entity
@Table(schema = "MCWAGNER", name = "xxxx_USERS")
public class xxxxUsersEntity implements Serializable {

private Long uid;
private String lastName;
private String firstName;
private List<AddressEntity> address = new ArrayList<AddressEntity>();

@Id
@Column(name = "USER_ID", nullable = false, length = 10)
@GeneratedValue(generator="UsrSeq")
@SequenceGenerator(name="UsrSeq",sequenceName="USER_SEQUENCE")
public Long getUid() {
return uid;
}

public void setUid(Long uid) {
this.uid = uid;
}

@Basic
@Column(name = "LAST_NAME", nullable = false, length = 20)
public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}



@Basic
@Column(name = "FIRST_NAME", nullable = false, length = 20)
public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

@ManyToMany(targetEntity = AddressEntity.class,
cascade ={CascadeType.PERSIST})
@JoinTable(
name = "USER_ADDRESS",
joinColumns = {@JoinColumn(name = "USR_ID")},
inverseJoinColumns = {@JoinColumn(name = "ADR_ID")}
)
public List<AddressEntity> getAddress() {
return address;
}

public void setAddress(List<AddressEntity> address) {
this.address = address;
}
}

package com.xxxx.users;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;

@Entity
@Table(schema = "MCWAGNER", name = "ADDRESS")
public class AddressEntity implements Serializable {

private Long aid;
private String city;
private String street;
private String zip;
private String state;
private List<xxxxUsersEntity> users = new ArrayList<XxxxUsersEntity>();

@Id
@Column(name = "ADDRESS_ID", nullable = false, length = 10)
@GeneratedValue(generator="AdrSeq")
@SequenceGenerator(name="AdrSeq",sequenceName="ADDRESS_SEQUENCE")
public Long getAid() {
return aid;
}

public void setAid(Long aid) {
this.aid = aid;
}

@Basic
@Column(name = "STREET", nullable = false, length = 50)
public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

@Basic
@Column(name = "CITY", nullable = false, length = 20)
public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

@Basic
@Column(name = "STATE", nullable = false, length = 2)
public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

@Basic
@Column(name = "ZIP", nullable = false, length = 5)
public String getZip() {
return zip;
}

public void setZip(String zip) {
this.zip = zip;
}


@ManyToMany(targetEntity = xxxxUsersEntity.class)
@JoinTable(
name = "USER_ADDRESS",
joinColumns = {@JoinColumn(name = "ADR_ID")},
inverseJoinColumns = {@JoinColumn(name = "USR_ID")}
)
public List<xxxxUsersEntity> getUsers() {
return users;
}

public void setUsers(List<xxxxUsersEntity> users) {
this.users = users;
}
}
Code between sessionFactory.openSession() and session.close():

xxxxUsersEntity user = new xxxxUsersEntity();
user.setLastName("Ratcliffe");
user.setFirstName("John");

AddressEntity address = new AddressEntity();
address.setStreet("1234 Powatan Circle");
address.setCity("Jamestown");
address.setState("VA");
address.setZip("23606");

user.getAddress().add(address);
session.save(user);
System.out.println("Record Inserted");

Full stack trace of any exception that occurs:

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.xxxx.users.AddressEntity
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:78)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:755)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1143)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:26)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:145)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at com.xxxx.users.AddUser.main(AddUser.java:29)
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:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)

Name and version of the database you are using:

Oralce 10g 10.2.0


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 2:04 pm 
Newbie

Joined: Fri Jul 25, 2008 2:22 pm
Posts: 3
I'm not an expert of hibernate, but maybe I can help a little here.

If you check the documentation for the ManyToMany relationship you will see this "As seen previously, the other side don't have to (must not) describe the physical mapping: a simple mappedBy argument containing the owner side property name bind the two."
That means that you have to describe the relationship (joinColumns, etc) in one side and in the other just use the mappedBy to indicate that the relation is described on the other side. Follow the link and check the example.

Please post and tell me if this was usefull and if you have other problems.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 2:42 pm 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
Sometimes a really, really simple example will help out.

Check out this tutorial on mapping a many-to-many relationship, taking a very simple scenario:

Mapping Many-to-Many Relationships with Hibernate and JPA Annotations


Image

Code:
package com.examscam.mappings;
import java.util.*;
import javax.persistence.*;

@Entity
public class LeftManyStudent {

  long id;
  String studentName;
  List<RightManyCourse> courses = new Vector();


  @ManyToMany
  @JoinTable(name = "join_table",
joinColumns = { @JoinColumn(name = "lmstudent_id")},
inverseJoinColumns={@JoinColumn(name="rmcourse_id")}   
  )
  public List<RightManyCourse> getCourses(){
    return courses;
  }
  public void setCourses(List<RightManyCourse> righties){
    this.courses = righties;
  }

  @Id
  @GeneratedValue
  public long getId() {return id;}
  public void setId(long id) {this.id = id;}

  public String getStudentName() {
    return studentName;
  }
  public void setStudentName(String s){
    studentName=s;
  }

}


Image

Image

Code:
package com.examscam.mappings;

import java.util.*;
import javax.persistence.*;

@Entity
public class RightManyCourse {
  long id;
  String courseCode;
  List<LeftManyStudent> students = new Vector();

@ManyToMany
@JoinTable(name = "join_table",
joinColumns={@JoinColumn(name="rmcourse_id")},
inverseJoinColumns={@JoinColumn(name="lmstudent_id")})
  public List<LeftManyStudent> getStudents() {
    return students;
  }
  public void setStudents(List<LeftManyStudent> lefties){
    this.students = lefties;
  }

  @Id
  @GeneratedValue
  public long getId() {
    return id;
  }
  public void setId(long id) {
    this.id = id;
  }

  public String getCourseCode() {
    return courseCode;
  }
  public void setCourseCode(String courseCode) {
    this.courseCode = courseCode;
  }

}


Image

Code:
public static void main (String args[]) {
HibernateUtil.recreateDatabase();

  LeftManyStudent student01 = new LeftManyStudent();
  student01.setStudentName("Jim Jump");
  LeftManyStudent student02 = new LeftManyStudent();
  student02.setStudentName("Julie Camp");
  LeftManyStudent student03 = new LeftManyStudent();
  student03.setStudentName("Cam Johnson");
  LeftManyStudent student04 = new LeftManyStudent();
  student04.setStudentName("Marcus McKenzie");
  RightManyCourse java101 = new RightManyCourse();
  java101.setCourseCode("Java-101");
  RightManyCourse cplus101 = new RightManyCourse();
  cplus101.setCourseCode("C++ - 101");
  RightManyCourse math101 = new RightManyCourse();
  math101.setCourseCode("Math - 101");

  java101.getStudents().add(student01);
  java101.getStudents().add(student02);
  java101.getStudents().add(student03);
  cplus101.getStudents().add(student02);
  cplus101.getStudents().add(student03);
  math101.getStudents().add(student04);

  Session session = HibernateUtil.beginTransaction();
  session.save(student01);
  session.save(student02);
  session.save(student03);
  session.save(student04);
  session.save(java101);
  session.save(cplus101);
  session.save(math101);
  HibernateUtil.commitTransaction();
}

_________________
Cameron McKenzie - Author of "Hibernate Made Easy" and "What is WebSphere?"
http://www.TheBookOnHibernate.com Check out my 'easy to follow' Hibernate & JPA Tutorials


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 3:01 pm 
Newbie

Joined: Fri Jul 25, 2008 10:40 am
Posts: 3
athegra wrote:
Please post and tell me if this was usefull and if you have other problems.


A good suggestion. I did try this with and without the targetEntity tag, to no avail.

Cameron McKenzie wrote:

Code:
  Session session = HibernateUtil.beginTransaction();
  session.save(student01);
  session.save(student02);
  session.save(student03);
  session.save(student04);
  session.save(java101);
  session.save(cplus101);
  session.save(math101);
  HibernateUtil.commitTransaction();
}


Code:
xxxxUsersEntity user = new xxxxUsersEntity();
            user.setLastName("Ratcliffe");
            user.setFirstName("John");

            AddressEntity address = new AddressEntity();
            address.setStreet("1234 Powatan Circle");
            address.setCity("Jamestown");
            address.setState("VA");
            address.setZip("23606");

            user.getAddress().add(address);
           
            session.save(user);
            session.save(address);
       
            System.out.println("Record Inserted");
            session.getTransaction().commit();
            session.close();


Trying this method and got the following:

Exception in thread "main" org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:145)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at com.xxxx.users.AddUser.main(AddUser.java:30)
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:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Caused by: java.sql.BatchUpdateException: ORA-00904: "ADR_ID": invalid identifier

at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10698)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
... 13 more

I am at a loss, for sure!

Thanks in advance,
Mark


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 3:36 pm 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
SQLGrammer means your tables or column names in the database don't match your class or property names in your Java code.

Something about the ADR_ID?

-Cameron McKenzie

_________________
Cameron McKenzie - Author of "Hibernate Made Easy" and "What is WebSphere?"
http://www.TheBookOnHibernate.com Check out my 'easy to follow' Hibernate & JPA Tutorials


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 8:39 pm 
Newbie

Joined: Fri Jul 25, 2008 10:40 am
Posts: 3
What solved it was your first post. I forgot to refresh the datasource in IntelliJ to point to the proper join table (i have had several versions of it).

Thanks to you both for your input!

Mark


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.