Verifying Many to One Bidirectional Hibernate Mapping using Domain Files created by hbm2java

Next we move onto how we use the generated classes in the post below to develop a hibernate application that demonstrates many to one bidirectional relationship. We have a little bit of spring but the highlight is to demonstrate hibernate capabilities.
Refer
http://cuppajavamattiz.com/2012/01/20/hibernate-mappings-with-hbm-xml-files/
and
http://cuppajavamattiz.com/2012/01/30/domain-java-files-from-hibernate-mapping-files/
First we would need to create a database with the following DDL for mySQL:

script

drop database hibemappings;
create database hibemappings;
use hibemappings;
create table Book (isbn_code bigint(3) not null auto_increment, book_title varchar(30), primary key(isbn_code));
create table Author (author_id bigint(3) not null auto_increment, isbn_code_in_author bigint(3), first_name varchar(30), last_name varchar(30), primary key(author_id), foreign Key (isbn_code_in_author) references Book(isbn_code));

The workspace for the project has the following structure on eclipse:

<project>
     <com.mattiz.persistence.beans>
          ...copy over the generated domain files from previous post
          BookWithMultipleAuthors.java
          ContributingAuthor.java
     <com.mattiz.persistnece.data>
          MappingDAO.java
          MappingDAOImpl.java
     <com.mattiz.service.spring>
          AppInvoker.java
     <resources>
         author.hbm.xml(same mapping file used to generate domain files as in previous post)
         book.hbm.xml(same mapping file used to generate domain files as in previous post)
         mattiz.xml(spring configuration file)

I have put most of the jars in http://cuppajavamattiz.com/2008/06/14/migrating-to-a-standalone-spring-hibernate-application/ example on the classpath with a minor change. In addition I have added \spring-framework-2.5.4-with-dependencies\spring-framework-2.5.4\lib\cglib\cglib-nodep-2.1_3.jar also on the classpath.

Copy over the domain classes generated by the hbm2 java and the hbml.xml files to the location shown above. (See previous post)

Note the lazy=false in both hibernate mapping files at two locations by which we enforce eager fetch.

mattiz.xml is the spring configuration file which provides the Spring’s hibernate support to our DAO:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="mattiz.hibernate.dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<property name="driverClass" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/hibemappings" />
		<property name="user" value="root" />
		<property name="password" value="admin" />
	</bean>
	<bean id="mattiz.abstract.hibernate.sessionfactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
		abstract="true" lazy-init="true">
		<property name="dataSource">
			<ref local="mattiz.hibernate.dataSource" />
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">false</prop>
			</props>
		</property>
	</bean>
	<bean id="mattiz.pageSize" class="java.lang.Integer">
		<constructor-arg value="5000"></constructor-arg>
	</bean>
	<bean id="mattiz.hibernate.sessionfactory" parent="mattiz.abstract.hibernate.sessionfactory">
		<property name="mappingResources">
			<list>
				<value>resources/author.hbm.xml</value>
				<value>resources/book.hbm.xml</value>
			</list>
		</property>
	</bean>
	<bean id="mattiz.transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref bean="mattiz.hibernate.sessionfactory" />
		</property>
	</bean>
	<bean id="mattiz.hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
		<property name="sessionFactory">
			<ref bean="mattiz.hibernate.sessionfactory" />
		</property>
	</bean>
	<bean id="mattiz.mattizDAO" class="com.mattiz.persistence.data.MappingDAOImpl"
		singleton="true">
		<property name="hibernateTemplate">
			<ref bean="mattiz.hibernateTemplate" />
		</property>
	</bean>
</beans>

We write the following java classes to demonstrate the many to one bidirectional relationship:

MappingDAO.java

package com.mattiz.persistence.data;
 
import java.util.Set;
import com.mattiz.persistence.beans.BookWithMultipleAuthors;
import com.mattiz.persistence.beans.ContributingAuthor;
 
public interface MappingDAO {
     
    public Set<ContributingAuthor> getContributingAuthors(long isbnCode);
 
    public BookWithMultipleAuthors getBookForAuthor(long authorId);
 
    public void initializeDB();
}

MappingDAOImpl.java

package com.mattiz.persistence.data;
 
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.mattiz.persistence.beans.BookWithMultipleAuthors;
import com.mattiz.persistence.beans.ContributingAuthor;
 
public class MappingDAOImpl implements MappingDAO {
    private HibernateTemplate hibernateTemplate;
 
    public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }
 
    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }
 
    public Set<ContributingAuthor> getContributingAuthors(long isbnCode) {
        BookWithMultipleAuthors bookWithMultipleAuthors = (BookWithMultipleAuthors) getHibernateTemplate()
                .load(BookWithMultipleAuthors.class, isbnCode);
        Set<ContributingAuthor> authors = bookWithMultipleAuthors
                .getContributingAuthors();
        Iterator<ContributingAuthor> i = authors.iterator();
        while (i.hasNext()) {
            System.out.println("Author "
                    + ((ContributingAuthor) i.next()).getFirstName());
        }
        return authors;
    }
 
    public BookWithMultipleAuthors getBookForAuthor(long authorId) {
        ContributingAuthor contributingAuthor = (ContributingAuthor) getHibernateTemplate()
                .load(ContributingAuthor.class, authorId);
        BookWithMultipleAuthors book = contributingAuthor
                .getBookContributedToByAuthor();
        System.out.println("BOOK " + book.getTitle());
        return book;
    }
 
    public void initializeDB() {// fill up db with random named AUTHORs and
                                // BOOKs
        HibernateTemplate template = getHibernateTemplate();
        BookWithMultipleAuthors bookEntity = new BookWithMultipleAuthors();
        Random random = new Random();
        int ran = generateRandomInteger(65, 74, random);// boiler plate code
        bookEntity.setTitle(new String(new char[] { (char) ran,
                (char) (ran + 3), (char) (ran + 10), (char) (ran + 15) }));
        template.saveOrUpdate(bookEntity);
        System.out.println("Inserted Book, ISBN, Title:  "
                + bookEntity.getIsbnCode() + " " + bookEntity.getTitle());
        for (int i = 0; i < 10; i++) {
            ran = generateRandomInteger(65, 85, random);
            ContributingAuthor contributingAuthor = newContributingAuthor(ran,
                    bookEntity);
            System.out.println("Inserted Author, First and last name:  "
                    + contributingAuthor.getFirstName() + " "
                    + contributingAuthor.getLastName());
        }
    }
 
    private ContributingAuthor newContributingAuthor(int i,
            BookWithMultipleAuthors bookEntity) {
        HibernateTemplate template = getHibernateTemplate();
        ContributingAuthor contributingAuthor = new ContributingAuthor();
        contributingAuthor.setBookId(i);
        contributingAuthor.setFirstName(new String(new char[] { (char) (i + 2),
                (char) (i + 1), (char) (i + 3) }));
        contributingAuthor.setLastName(new String(new char[] { (char) (i + 3),
                (char) (i + 2), (char) (i + 4) }));
        contributingAuthor.setBookContributedToByAuthor(bookEntity);
        template.save(contributingAuthor);
        return contributingAuthor;
    }
 
    private static int generateRandomInteger(int aStart, int aEnd,
            Random aRandom) {// boiler plate code to generate ascii code for A-Z
        if (aStart > aEnd) {
            throw new IllegalArgumentException("Start cannot exceed End.");
        }
        long range = (long) aEnd - (long) aStart + 1;
        long fraction = (long) (range * aRandom.nextDouble());
        int randomNumber = (int) (fraction + aStart);
        return randomNumber;
    } 
}

AppInvoker.java

package com.mattiz.service.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mattiz.persistence.data.MappingDAO;
import com.mattiz.persistence.data.MappingDAOImpl;

public class AppInvoker {
	private ApplicationContext applicationContext;
	private MappingDAO mappingDAOImpl;

	public static void main(String[] args) {
		AppInvoker appInvoker = new AppInvoker();
		appInvoker.setApplicationContext(new ClassPathXmlApplicationContext(
				"resources/mattiz.xml"));
		appInvoker.getMappingDAO().initializeDB();
		appInvoker.getMappingDAO().getContributingAuthors(2L);// demonstrates one to many
		appInvoker.getMappingDAO().getBookForAuthor(11);// demonstrates many to one
	}

	public MappingDAO getMappingDAO() {
		mappingDAOImpl = (MappingDAOImpl) applicationContext
				.getBean("mattiz.mattizDAO");
		return mappingDAOImpl;
	}

	public void setMapppingDAO(MappingDAO mappingDAOImpl) {
		this.mappingDAOImpl = mappingDAOImpl;
	}

	public ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}
}

On running the main class in AppInvoker.java you may see an output similar to this on the console:

Inserted Book, ISBN, Title:  9 GJQV
Inserted Author, First and last name:  NMO ONP
Inserted Author, First and last name:  RQS SRT
Inserted Author, First and last name:  JIK KJL
Inserted Author, First and last name:  LKM MLN
Inserted Author, First and last name:  HGI IHJ
Inserted Author, First and last name:  CBD DCE
Inserted Author, First and last name:  RQS SRT
Inserted Author, First and last name:  UTV VUW
Inserted Author, First and last name:  LKM MLN
Inserted Author, First and last name:  GFH HGI
Author HGI
Author LKM
Author QPR
Author POQ
Author ONP
Author FEG
Author TSU
Author GFH
Author EDF
Author MLN
BOOK EHOT

The database might look something like this – verify the mapping->

mysql> select * from book;

+-----------+------------+
| isbn_code | book_title |
+-----------+------------+
|         1 | ILSX       |
|         2 | EHOT       |
|         3 | CFMR       |
|         4 | FIPU       |
|         5 | GJQV       |
|         6 | EHOT       |
|         7 | HKRW       |
|         8 | BELQ       |
|         9 | GJQV       |
+-----------+------------+
9 rows in set (0.00 sec)

mysql> select * from author;
+-----------+---------------------+------------+-----------+
| author_id | isbn_code_in_author | first_name | last_name |
+-----------+---------------------+------------+-----------+
|         1 |                   1 | CBD        | DCE       |
|         2 |                   1 | MLN        | NMO       |
|         3 |                   1 | MLN        | NMO       |
|         4 |                   1 | GFH        | HGI       |
|         5 |                   1 | FEG        | GFH       |
|         6 |                   1 | ONP        | POQ       |
|         7 |                   1 | VUW        | WVX       |
|         8 |                   1 | RQS        | SRT       |
|         9 |                   1 | GFH        | HGI       |
|        10 |                   1 | FEG        | GFH       |
|        11 |                   2 | FEG        | GFH       |
|        12 |                   2 | QPR        | RQS       |
|        13 |                   2 | HGI        | IHJ       |
|        14 |                   2 | LKM        | MLN       |
|        15 |                   2 | TSU        | UTV       |
|        16 |                   2 | MLN        | NMO       |
|        17 |                   2 | ONP        | POQ       |
|        18 |                   2 | GFH        | HGI       |
|        19 |                   2 | EDF        | FEG       |
|        20 |                   2 | POQ        | QPR       |
|        21 |                   3 | LKM        | MLN       |
|        22 |                   3 | VUW        | WVX       |
|        23 |                   3 | DCE        | EDF       |
|        24 |                   3 | ONP        | POQ       |
|        25 |                   3 | UTV        | VUW       |
|        26 |                   3 | DCE        | EDF       |
|        27 |                   3 | SRT        | TSU       |
|        28 |                   3 | IHJ        | JIK       |
|        29 |                   3 | NMO        | ONP       |
|        30 |                   3 | SRT        | TSU       |
|        31 |                   4 | RQS        | SRT       |
|        32 |                   4 | MLN        | NMO       |
|        33 |                   4 | RQS        | SRT       |
|        34 |                   4 | FEG        | GFH       |
|        35 |                   4 | HGI        | IHJ       |
|        36 |                   4 | EDF        | FEG       |
|        37 |                   4 | GFH        | HGI       |
|        38 |                   4 | VUW        | WVX       |
|        39 |                   4 | LKM        | MLN       |
|        40 |                   4 | SRT        | TSU       |

Folder structure here heirarchy

The source code can be downloaded here

About cuppajavamattiz
Matty Jacob - Avid technical blogger with interests in J2EE, Web Application Servers, Web frameworks, Open source libraries, Relational Databases, Web Services, Source control repositories, ETL, IDE Tools and related technologies.

Comments are closed.