• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Inserting data in Intermediate table on the Many-to-Many

 
Selva Varadhan
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi i 'm new to the Hibernate and i 'm trying different kind of mappings
When i 'm doing many-to-many mapping, i 'm not able to insert the data in Intermediate table( consist of both the tables primary keys)

I 'm dong many-to-many mapping for Employee and Project.

EMPLOYEE Table consist of EMPID,NAME
PROJECT Table consist of PROID, PROJECT_NAME
Mapping table ( EMP_PROJECT ) consist of EMPID, PROID

my mappinc xmls

Hibernate version:3.0

Mapping documents:

Mapping for Employee
<hibernate-mapping package="mapping/many2many" auto-import="false">
<class name="Employee" table="EMPLOYEE" lazy="true">
<id name="empId" column="EMPID">
<generator class="increment"/>
</id>
<property name="name" column="NAME"/>
<set name="projects" table="EMP_PROJECT" cascade="all" inverse="true">
<key column="EMPID"/>
<many-to-many class="Project" column="PROID">
</many-to-many>
</set>

</class>
</hibernate-mapping>

Mapping for Project
<hibernate-mapping package="mapping/many2many" auto-import="false">
<class name="Project" table="PROJECT" lazy="true">
<id name="proId" column="PROID">
<generator class="increment"/>
</id>
<property name="project_name" column="PRO_NAME"/>
<set name="employee" table="EMP_PROJECT" cascade="all" inverse="true">
<key column="PROID"/>
<many-to-many class="Employee" column="EMPID">
</many-to-many>
</set>
</class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
txn = ses.beginTransaction();
Employee emp = new Employee();
emp.setName("Name1");

Employee emp2 = new Employee();
emp2.setName("Name2");

Project project2 = new Project();
project2.setProject_name("Project");
project2.setItem(emp);
project2.setItem(emp2);

ses.save(project2);
txn.commit();



Name and version of the database you are using:

HSQLDB server 1.7.1

The generated SQL (show_sql=true):
Hibernate: insert into PROJECT (PRO_NAME, PROID) values (?, ?)
Hibernate: insert into EMPLOYEE (NAME, EMPID) values (?, ?)
Hibernate: insert into EMPLOYEE (NAME, EMPID) values (?, ?)
 
Thomas Bigbee
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Selva

The below works using annotations, however that may not be the problem, Hibernate uses lazy loading by default, if you check the value of your Set it would be null

Example:
tx = session.beginTransaction();
List authorList = session.createQuery("from Author").list();

Iterator aIter = authorList.iterator();

while ( aIter.hasNext()) {
System.out.println("in while");
a = (Author)aIter.next();
Set <Book>aSet = a.getBooks();
Iterator bIter = aSet.iterator();
while ( bIter.hasNext()){
Book b = (Book)bIter.next();
System.out.println("the book for the autor is:" + b.getTitle());
}
System.out.println("Id " + a.getId() + " Name " + a.getName());
}

(in the Books.class)
protected Set <Book> books = new HashSet<Book>();


Notice how I have to call getBooks, even though in the author class, books is defined, it is null until you go out and get it by calling the getter method in the POJO, you can however specify that one table will be automatically joined (and only one table) when you execute your qurey, the rest would be lazily loaded.

By the way, I just got back from Advanced Hibernate Training in Atlanta specified that Annotations are the way to go, as opposed to Mapping Files, the best book I've found so far is Pro Hibernate 3 (even though there are a number of errors, they were using an early alpha version for the book)



I hava a Book class and table and an Author class ant table and a
intermediate table called Book_Author which consists of Book_Id and
Author_Id

Book Class (pk = id)

@ManyToMany (fetch=FetchType.LAZY,
targetEntity=com.hibernatebook.annotations.Author.class,
cascade={CascadeType.PERSIST, CascadeType.MERGE}
)
@JoinTable(
table=@Table(name="Author_Book"),
joinColumns={@JoinColumn(name="Book_Id")},
inverseJoinColumns={@JoinColumn(name="Author_Id")}
)
public Set<Author>getAuthors() {
return authors;
}



Author Class (pk = id)

@ManyToMany(cascade = {CascadeType.ALL}, mappedBy = "authors")
public Set<Book>getBooks() {
return books;
}


Hope this helps, Tom
 
Selva Varadhan
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Tom,
I understood the lazy loading, but my problem here is, i 'm not able to insert the data in the intemediate table(EMP_PROJECT). While running my application data is inserted on in the EMPLOYEE and PROJECT Table but not in the EMP_PROJECT table.

Plz go through my mapping file(employee.hbm.xml and project.hbm.xml) i posted and let me know if i did any thing wrong on that. If possible give me a sample.

Thanks,
Selva Varadhan
 
Thomas Bigbee
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are adding employees to a project, try adding projects to employees. I may be misspeaking, however, let me try to explain. When you use inverse="true" in the project.hbm.xml you are telling Hibernate that changes to Projects (involving employees) are not to be recorded, and that the Employee table is the main table. You should always use an 'inverse="true"' on the many side of the realtionship.

In order to test this out I created your app from scratch, I then had it working, I plugged in your example code, guess what? not only did the emp_proj table not get populated but the employee table was empty as well. Save the employees as you go along, then before you add your projects flush() your changes to the DataBase.

Like I mentioned before, you may want to get rid of the mapping files and go stricly with Annotations, there much easier to use and alot easier to program and debug.


[ October 04, 2005: Message edited by: Thomas Bigbee ]
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic