In earlier post we had OneToMany bi-directional mapping. In this post we will see how can we make it unidirectional with the usage of a JoinTable.
Let’s create our eclipse project and then add update our pom.xml.
pom.xml
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion>4.0.0</modelVersion> <groupId>com.mumz.test.hibernatesearch</groupId> <artifactId>MumzHibernateSearch</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>MumzHibernateSearch</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate.javax.persistence</groupId> <artifactId>hibernate-jpa-2.0-api</artifactId> <version>1.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.1.7.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.1.7.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> </dependencies> </project>
Next we will write our Entity to model Book and BookShelf tables. BookShelf will contain a set of books. First we will write our MHSBookEntityBean.
MHSBookEntityBean.java
package com.mumz.test.hibernatesearch.entitybeans;
import java.io.Serializable;
import java.lang.Long;
import java.lang.String;
import javax.persistence.*;
/**
* The Class MHSBookEntityBean.
* @author prabhat.jha
*/
@Entity
@Table(name = "BOOK")
public class MHSBookEntityBean implements Serializable {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -5129783468137830152L;
/** The id. */
private Long id = null;
/** The name. */
private String name = null;
/** The author. */
private String author = null;
/**
* Instantiates a new mHS book entity bean.
*/
public MHSBookEntityBean() {
super();
}
/**
* Gets the id.
*
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "BOOK_ID")
public Long getId() {
return this.id;
}
/**
* Sets the id.
*
* @param id
* the new id
*/
public void setId(Long id) {
this.id = id;
}
/**
* Gets the name.
*
* @return the name
*/
@Column(name = "BOOK_NAME")
public String getName() {
return this.name;
}
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the author.
*
* @return the author
*/
@Column(name = "BOOK_AUTHOR")
public String getAuthor() {
return author;
}
/**
* Sets the author.
*
* @param author
* the new author
*/
public void setAuthor(String author) {
this.author = author;
}
/** (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((author == null) ? 0 : author.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/** (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof MHSBookEntityBean)) {
return false;
}
MHSBookEntityBean other = (MHSBookEntityBean) obj;
if (author == null) {
if (other.author != null) {
return false;
}
} else if (!author.equals(other.author)) {
return false;
}
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
return true;
}
/** (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "MHSBookEntityBean [id=" + id + ", name=" + name + ", author=" + author + "]";
}
}
Next we will write our MHSBookShelfEntityBean
MHSBookShelfEntityBean.java
package com.mumz.test.hibernatesearch.entitybeans;
import java.io.Serializable;
import java.lang.Long;
import java.lang.String;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
/**
* The Class MHSBookShelfEntityBean.
*
* @author prabhat.jha
*/
@Entity
@Table(name = "BOOK_SHELF")
public class MHSBookShelfEntityBean implements Serializable {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -7127365575633206221L;
/** The id. */
private Long id;
/** The name. */
private String name;
/** The books. */
private Set<MHSBookEntityBean> books = new HashSet<MHSBookEntityBean>();
/**
* Instantiates a new mHS book shelf entity bean.
*/
public MHSBookShelfEntityBean() {
super();
}
/**
* Gets the id.
*
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "BOOK_SHELF_ID")
public Long getId() {
return this.id;
}
/**
* Sets the id.
*
* @param id
* the new id
*/
public void setId(Long id) {
this.id = id;
}
/**
* Gets the name.
*
* @return the name
*/
@Column(name = "BOOK_SHELF_NAME")
public String getName() {
return this.name;
}
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the books.
*
* @return the books
*/
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "BOOK_SHELF_BOOK_MAPPING", joinColumns = {
@JoinColumn(name = "BOOK_SHELF_ID", referencedColumnName = "BOOK_SHELF_ID")
}, inverseJoinColumns = {
@JoinColumn(name = "BOOK_ID", referencedColumnName = "BOOK_ID", unique = true)
})
public Set<MHSBookEntityBean> getBooks() {
return books;
}
/**
* Sets the books.
*
* @param books
* the new books
*/
public void setBooks(Set<MHSBookEntityBean> books) {
this.books = books;
}
/**
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((books == null) ? 0 : books.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/**
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof MHSBookShelfEntityBean)) {
return false;
}
MHSBookShelfEntityBean other = (MHSBookShelfEntityBean) obj;
if (books == null) {
if (other.books != null) {
return false;
}
} else if (!books.equals(other.books)) {
return false;
}
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
return true;
}
/**
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "MHSBookShelfEntityBean [id=" + id + ", name=" + name + ", books=" + books + "]";
}
}
Highlighted code above signifies the Join table usage.
Finally our persistence.xml and some test code to check our model.
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" >
<persistence-unit name="MumzJPA" transaction-type="RESOURCE_LOCAL">
<class>com.mumz.test.hibernatesearch.entitybeans.MHSBookEntityBean</class>
<class>com.mumz.test.hibernatesearch.entitybeans.MHSBookShelfEntityBean</class>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.password" value="root"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/jpa_schema"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
</persistence>
TestOneToManyJoinTable.java
package com.mumz.test.hibernatesearch.entitybeans;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
/**
* The Class TestOneToManyJoinTable.
* @author prabhat.jha
*/
public class TestOneToManyJoinTable {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
EntityManager entityManager = Persistence.createEntityManagerFactory("MumzJPA").createEntityManager();
try {
Set<MHSBookEntityBean> books = new HashSet<MHSBookEntityBean>();
MHSBookEntityBean mhsBookEntityBean = new MHSBookEntityBean();
mhsBookEntityBean.setName("Java EE Pocket Guide");
mhsBookEntityBean.setAuthor("Arun Gupta");
books.add(mhsBookEntityBean);
mhsBookEntityBean = new MHSBookEntityBean();
mhsBookEntityBean.setName("Pro Android 4");
mhsBookEntityBean.setAuthor("Satya Komatineni and Dave MacLean");
books.add(mhsBookEntityBean);
MHSBookShelfEntityBean bookShelfEntityBean = new MHSBookShelfEntityBean();
bookShelfEntityBean.setName("Technical Books");
bookShelfEntityBean.setBooks(books);
entityManager.getTransaction().begin();
entityManager.persist(bookShelfEntityBean);
entityManager.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
entityManager.getTransaction().rollback();
} finally {
if (entityManager != null) {
entityManager.close();
}
entityManager = null;
}
}
}
Database schema used for this code.
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
DROP SCHEMA IF EXISTS `jpa_schema` ;
CREATE SCHEMA IF NOT EXISTS `jpa_schema` DEFAULT CHARACTER SET utf8 ;
USE `jpa_schema` ;
-- -----------------------------------------------------
-- Table `jpa_schema`.`book`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jpa_schema`.`book` ;
CREATE TABLE IF NOT EXISTS `jpa_schema`.`book` (
`BOOK_ID` INT(11) NOT NULL AUTO_INCREMENT ,
`BOOK_AUTHOR` VARCHAR(45) NOT NULL ,
`BOOK_NAME` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`BOOK_ID`) )
ENGINE = InnoDB
AUTO_INCREMENT = 5
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `jpa_schema`.`book_shelf`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jpa_schema`.`book_shelf` ;
CREATE TABLE IF NOT EXISTS `jpa_schema`.`book_shelf` (
`BOOK_SHELF_ID` INT(11) NOT NULL AUTO_INCREMENT ,
`BOOK_SHELF_NAME` VARCHAR(45) NULL DEFAULT NULL ,
PRIMARY KEY (`BOOK_SHELF_ID`) )
ENGINE = InnoDB
AUTO_INCREMENT = 3
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `jpa_schema`.`book_shelf_book_mapping`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `jpa_schema`.`book_shelf_book_mapping` ;
CREATE TABLE IF NOT EXISTS `jpa_schema`.`book_shelf_book_mapping` (
`BOOK_SHELF_BOOK_MAP_ID` INT(11) NOT NULL AUTO_INCREMENT ,
`BOOK_ID` INT(11) NULL DEFAULT NULL ,
`BOOK_SHELF_ID` INT(11) NULL DEFAULT NULL ,
PRIMARY KEY (`BOOK_SHELF_BOOK_MAP_ID`) ,
INDEX `FK_BOOK_ID` (`BOOK_ID` ASC) ,
INDEX `FK_BOOK_SHELF_ID` (`BOOK_SHELF_ID` ASC) ,
CONSTRAINT `FK_BOOK_ID`
FOREIGN KEY (`BOOK_ID` )
REFERENCES `jpa_schema`.`book` (`BOOK_ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `FK_BOOK_SHELF_ID`
FOREIGN KEY (`BOOK_SHELF_ID` )
REFERENCES `jpa_schema`.`book_shelf` (`BOOK_SHELF_ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
AUTO_INCREMENT = 5
DEFAULT CHARACTER SET = utf8;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
I have a question here. I have company and it’s subscription as two tables. Subscription for me is a reference table which has fix data. So I am creating a new company and want to store it’s subscription in Join table. How can I achieve this. When I try above thing it’s trying to insert in subscription table which I don’t want.