Many to One Bidirectional Mapping using JPA and annotations

This is a JPA version of the many to one bidirectional hibernate mapping in this post – https://cuppajavamattiz.wordpress.com/2012/01/30/verifying-many-to-one-bidirectional-hibernate-mapping/
I am using JBoss Developer Studio 4.1.0 GA. I add JBoss AS server runtime to the classpath. This gives me the advantage of not explicitly including hibernate/ jpa jars on my classpath. Jboss AS server has inherent support for JPA through an underlying hibernate layer.
The only additional jars that I add to the project are from the spring 3.1.1 RELEASE. This is also necessary because I use some features that are supported by the 3.1.1 version – namely the doing away of a separate persistence.xml. I do not use the jboss server instance to run the application though, since like the last example this one too, is a standalone Java project, to keep things simple.
This example uses JPA and the source code has no hibernate references except for the database configuration file. This gives the advantage of DAO layer portability with which you could port the app over to TopLink, EJB3 or Ibatis which like Hiberenate also implement JPA, without any source code changes.
As in the last example we use the following 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));

I have modified the generated domain classes in this post – http://cuppajavamattiz.com/2012/01/30/domain-java-files-from-hibernate-mapping-files
– to make it JPA enabled.
The project heirarchy looks like this

The domain classes:

package com.mattiz.persistence.beans;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "book")
public class BookWithMultipleAuthors implements java.io.Serializable {
	private static final long serialVersionUID = -5923630089211813669L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "isbn_code")
	private long isbnCode;

	@Column(name = "book_title")
	private String title;

	public BookWithMultipleAuthors() {
	}
	public long getIsbnCode() {
		return isbnCode;
	}
	public void setIsbnCode(long isbnCode) {
		this.isbnCode = isbnCode;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
}
package com.mattiz.persistence.beans;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.JoinColumn;

@Entity
@Table(name = "author")
public class ContributingAuthor implements java.io.Serializable {
	private static final long serialVersionUID = 6984629859445330115L;
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "author_id")
	private long authorId;

	@Column(name = "first_name")
	private String firstName;

	@Column(name = "last_name")
	private String lastName;

	@ManyToOne
	@JoinColumn(name = "isbn_code_in_author", referencedColumnName = "isbn_code")
	private BookWithMultipleAuthors bookContributedToByAuthor;

	public ContributingAuthor() {
	}
	public long getAuthorId() {
		return authorId;
	}
	public void setAuthorId(long authorId) {
		this.authorId = authorId;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public BookWithMultipleAuthors getBookContributedToByAuthor() {
		return bookContributedToByAuthor;
	}
	public void setBookContributedToByAuthor(
			BookWithMultipleAuthors bookContributedToByAuthor) {
		this.bookContributedToByAuthor = bookContributedToByAuthor;
	}
}

The spring configuration file – mattiz.xml:




    
        
        
        
        
    
    
        
    
    
        
    
    
        
        
        
            
        
        
            
                org.hibernate.dialect.MySQLDialect
            
        
        
            
                com.mattiz.persistence.beans
            
        
    

Note: I had to add the spring configuration file – mattiz.xml in the reources folder to the classpath so that the spring jars could locate it.
The DAO class:

package com.mattiz.persistence.data;
 
import java.util.List;
import java.util.Random;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import com.mattiz.persistence.beans.BookWithMultipleAuthors;
import com.mattiz.persistence.beans.ContributingAuthor;
 
public class MappingDAOImpl implements MappingDAO {
 
    @PersistenceUnit(unitName = "MattizDomainUnit")
    private static EntityManagerFactory emf;
 
    @PersistenceContext
    private static EntityManager em;
 
    @SuppressWarnings("unchecked")
    public List getContributingAuthors(long isbnCode) {
        List result = null;
        try {
            String jpaql = "select e from BookWithMultipleAuthors e "
                    + "where e.isbnCode= ?1 ";
            startTransaction();
            Query query = createEntityManager().createQuery(jpaql)
                    .setParameter(1, isbnCode);
            result = query.getResultList();
            commit();
        } catch (PersistenceException e) {
            throw new RuntimeException(e);
        }
        return result;
    }
 
    @SuppressWarnings("unchecked")
    public BookWithMultipleAuthors getBookForAuthor(long authorId) {
        startTransaction();
        ContributingAuthor contributingAuthor = (ContributingAuthor) createEntityManager()
                .find(ContributingAuthor.class, authorId);
        BookWithMultipleAuthors book = contributingAuthor
                .getBookContributedToByAuthor();
        commit();
        System.out.println("BOOK " + book.getTitle());
        return book;
    }
 
    public void initializeDB() {// fill up db with random named AUTHORs and
                                // BOOKs
        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) }));
        startTransaction();
        createEntityManager().persist(bookEntity);
        commit();
        System.out.println("Inserted Book, ISBN, Title:  "
                + bookEntity.getIsbnCode() + " " + bookEntity.getTitle());
        for (int i = 0; i  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;
    }
 
    private static EntityManager createEntityManager() {
        if (emf == null) {
            emf = Persistence.createEntityManagerFactory("MattizDomainUnit");
        }
        if (em == null) {
            em = emf.createEntityManager();
        }
        return em;
    }
 
    private void commit() {
        try {
            EntityTransaction transaction = createEntityManager()
                    .getTransaction();
            transaction.commit();
 
        } catch (PersistenceException e) {
            e.printStackTrace();
            throw e;
        }
 
    }
 
    public void startTransaction() {
        try {
            EntityTransaction transaction = createEntityManager()
                    .getTransaction();
            if (!transaction.isActive()) {
                transaction.begin();
            }
        } catch (PersistenceException e) {
            e.printStackTrace();
            throw e;
        }
    }
}

The interface which this DAO implements:

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

The main class:

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(
				"mattiz.xml"));
		appInvoker.getMappingDAO().initializeDB();
		appInvoker.getMappingDAO().getContributingAuthors(3L);// demonstrates one to many
		appInvoker.getMappingDAO().getBookForAuthor(19);// 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;
	}
}

The ouput is similar to the one in this post – http://cuppajavamattiz.com/2012/01/30/verifying-many-to-one-bidirectional-hibernate-mapping

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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: