Hibernate @Any, @ManyToAny and @AnyMetaDef Annotation Example
August 28, 2016
This page will walk through hibernate @Any, @ManyToAny and @AnyMetaDef annotation example. @Any is ToOne style association and @ManyToAny is ToMany style association from an entity to any entity of several types. To distinguish an entity among several types, we need to use a discriminator value defined by @AnyMetaDef
. For reusability point of view @AnyMetaDef
should be used at package level. @Any
associates an entity with an entity of any type which are implementing a defined interface. @ManyToAny
is the collection valued form of @Any
annotation. Find the complete example of @Any
and @ManyToAny
mapping with @AnyMetaDef
annotation.
Contents
Gradle File
Find the gradle file used in our example.build.gradle
apply plugin: 'java' apply plugin: 'eclipse' archivesBaseName = 'hibernate' version = '1' repositories { mavenCentral() } dependencies { compile 'org.hibernate:hibernate-core:4.3.11.Final' compile 'mysql:mysql-connector-java:5.1.31' }
Database Table Creation using MySQL
I am using MySQL database. Find the tables used in our example.CREATE TABLE IF NOT EXISTS `boy` ( `id` int(11) NOT NULL, `age` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE IF NOT EXISTS `college` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE IF NOT EXISTS `college_students` ( `college_id` int(11) NOT NULL, `student_gender` varchar(255) DEFAULT NULL, `student_id` int(11) NOT NULL, KEY `FK_s48pbsjaf21n3wuc6q1v5jvq9` (`college_id`), CONSTRAINT `FK_s48pbsjaf21n3wuc6q1v5jvq9` FOREIGN KEY (`college_id`) REFERENCES `college` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE IF NOT EXISTS `girl` ( `id` int(11) NOT NULL, `age` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE IF NOT EXISTS `student_info` ( `id` int(11) NOT NULL, `student_gender` varchar(100) DEFAULT NULL, `student_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
@AnyMetaDef Annotation Example
@AnyMetaDef
is used as follows.
@AnyMetaDef(name= "StudentMetaDef", metaType = "string", idType = "int", metaValues = { @MetaValue(value = "B", targetEntity = Boy.class), @MetaValue(value = "G", targetEntity = Girl.class) } )
@Any
and @ManyToAny
mapping. @AnyMetaDef
can be used at property , class and package level. For the global reusability, hibernate recommends to use it at package level in package-info.java
.
name : It is global meta definition name. This name will be used by metaDef attribute of
@Any
and @ManyToAny
annotation.
metaType : It is the data type of value which will be inserted in the tables student_info and college_students with the mapping
@Any
and @ManyToAny
. In our example meta type is string and values are B and G.
idType : It is the data type for the id of the table in which data will be inserted with the mapping
@Any
and @ManyToAny
. In our case we are inserting int data type in our tables student_info and college_students.
@MetaValue : It maps a value to the target entity.
metaValues
attribute of @AnyMetaDef
collects all defined @MetaValue
.
In our example, we are using
@AnyMetaDef
at package level which is the recommended way.
package-info.java
@AnyMetaDef(name= "StudentMetaDef", metaType = "string", idType = "int", metaValues = { @MetaValue(value = "B", targetEntity = Boy.class), @MetaValue(value = "G", targetEntity = Girl.class) } ) package com.concretepage.entity; import org.hibernate.annotations.AnyMetaDef; import org.hibernate.annotations.MetaValue;
Hibernate XML Configuration
We need to configure our entities and package in whichpackage-info.java
resides. We are using @AnyMetaDef
at package level. So the package configuration is required. It is defined as below.
<mapping package="com.concretepage.entity"/>
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url"> jdbc:mysql://localhost:3306/concretepage</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"></property> <property name="hibernate.connection.pool_size">10</property> <property name="show_sql">true</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.hbm2ddl.auto">update</property> <mapping class="com.concretepage.entity.Boy"/> <mapping class="com.concretepage.entity.Girl"/> <mapping class="com.concretepage.entity.StudentInfo"/> <mapping class="com.concretepage.entity.College"/> <mapping package="com.concretepage.entity"/> </session-factory> </hibernate-configuration>
@Any Mapping Example
@Any
mapping is used as follows.
@Any( metaDef = "StudentMetaDef", metaColumn = @Column(name = "student_gender") )
Student
interface and two implementing classes Boy
and Girl
. If we want to store information of students irrespective of being girl or boy in StudentInfo
, we do mapping by @Any
.
metaDef : It maps the name defined by
@AnyMetaDef
annotation.
metaColumn : It defines the column name in which values is saved defined by
@MetaValue
of @AnyMetaDef
annotation.
Now find the example.
StudentInfo.java
package com.concretepage.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.Table; import org.hibernate.annotations.Any; @Entity @Table(name="student_info") public class StudentInfo { @Id private int id; @Any( metaDef = "StudentMetaDef", metaColumn = @Column(name = "student_gender") ) @JoinColumn( name = "student_id" ) private Student student; public int getId() { return id; } public void setId(int id) { this.id = id; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } }
package com.concretepage.entity; public interface Student { String getName(); int getAge(); }
package com.concretepage.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="boy") public class Boy implements Student { @Id private int id; @Column(name="name") private String name; @Column(name="age") private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
package com.concretepage.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="girl") public class Girl implements Student{ @Id private int id; @Column(name="name") private String name; @Column(name="age") private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
package com.concretepage; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static SessionFactory sessionFactory ; static { Configuration configuration = new Configuration().configure(); StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder(). applySettings(configuration.getProperties()); sessionFactory = configuration.buildSessionFactory(builder.build()); } public static SessionFactory getSessionFactory() { return sessionFactory; } public static void closeSessionFactory() { sessionFactory.close(); } }
package com.concretepage; import org.hibernate.Session; import com.concretepage.entity.Boy; import com.concretepage.entity.Girl; import com.concretepage.entity.StudentInfo; public class HibernateAnyDemo { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); Boy boy = new Boy(); boy.setId(1); boy.setName("Mukesh"); boy.setAge(30); session.persist(boy); Girl girl = new Girl(); girl.setId(1); girl.setName("Neerja"); girl.setAge(25); session.persist(girl); StudentInfo info1 = new StudentInfo(); info1.setId(1); info1.setStudent(boy); session.persist(info1); StudentInfo info2 = new StudentInfo(); info2.setId(2); info2.setStudent(girl); session.persist(info2); session.getTransaction().commit(); System.out.println("--data for id 1 --"); StudentInfo info = (StudentInfo) session.get(StudentInfo.class, 1); System.out.println("Name: "+info.getStudent().getName()); System.out.println("Age: "+info.getStudent().getAge()); System.out.println("--data for id 2 --"); info = (StudentInfo) session.get(StudentInfo.class, 2); System.out.println("Name: "+info.getStudent().getName()); System.out.println("Age: "+info.getStudent().getAge()); session.close(); HibernateUtil.closeSessionFactory(); } }
Hibernate: insert into boy (age, name, id) values (?, ?, ?) Hibernate: insert into girl (age, name, id) values (?, ?, ?) Hibernate: insert into student_info (student_gender, student_id, id) values (?, ?, ?) Hibernate: insert into student_info (student_gender, student_id, id) values (?, ?, ?) --data for id 1 -- Name: Mukesh Age: 30 --data for id 2 -- Name: Neerja Age: 25
@ManyToAny Mapping Example
@ManyToAny
mapping is used as follows.
@ManyToAny( metaDef = "StudentMetaDef", metaColumn = @Column(name = "student_gender") )
@ManyToAny : It defines ToMany style association from one entity to any entity of several types. It is collection-valued form of
@Any
.
metaDef : Maps the name defined by
@AnyMetaDef
annotation.
metaColumn : Defines the column name in which values is saved defined by
@MetaValue
of @AnyMetaDef
annotation.
Now find the example.
College.java
package com.concretepage.entity; import java.util.ArrayList; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.ManyToAny; @Entity @Table(name="college") public class College { @Id private int id; @Column(name="name") private String name; @ManyToAny( metaDef = "StudentMetaDef", metaColumn = @Column(name = "student_gender") ) @Cascade({org.hibernate.annotations.CascadeType.ALL}) @JoinTable(name = "college_students", joinColumns = @JoinColumn(name = "college_id"), inverseJoinColumns = @JoinColumn(name = "student_id") ) private List<Student> students = new ArrayList<>(); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } }
package com.concretepage; import java.util.ArrayList; import java.util.List; import org.hibernate.Session; import com.concretepage.entity.Boy; import com.concretepage.entity.College; import com.concretepage.entity.Girl; import com.concretepage.entity.Student; public class HibernateManyToAnyDemo { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); Boy boy = new Boy(); boy.setId(1); boy.setName("Mukesh"); boy.setAge(30); session.persist(boy); Girl girl = new Girl(); girl.setId(1); girl.setName("Neerja"); girl.setAge(25); session.persist(girl); College college = new College(); college.setId(1); college.setName("ABCD"); List<Student> students = new ArrayList<>(); students.add(boy); students.add(girl); college.setStudents(students); session.persist(college); session.getTransaction().commit(); College col = (College) session.get(College.class, 1); for(Student student: col.getStudents()) { System.out.println(student.getName()+":"+ student.getAge()); } session.close(); HibernateUtil.closeSessionFactory(); } }
Hibernate: insert into boy (age, name, id) values (?, ?, ?) Hibernate: insert into girl (age, name, id) values (?, ?, ?) Hibernate: insert into college (name, id) values (?, ?) Hibernate: insert into college_students (college_id, student_gender, student_id) values (?, ?, ?) Hibernate: insert into college_students (college_id, student_gender, student_id) values (?, ?, ?) Mukesh:30 Neerja:25