This type of relationships seems like an open one, because a record from either side is related to another on the other side. Let's consider one scenario. Here, we will use the Developer
and Technology
classes. In this scenario, multiple developers can associate with multiple technologies and vice versa.
Here, we will create the tables and classes to work this demo.
Use the following script to create the tables if you are not using hbm2dll=create|update
:
Use the following script to create the developer
table:
CREATE TABLE `developer` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) );
Use the following script to create the technology
table:
CREATE TABLE `technology` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `expertise` varchar(255) DEFAULT NULL, `language` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) );
Use the following script to create the developer_technology
table:
CREATE TABLE `developer_technology` ( `developer_id` bigint(20) NOT NULL, `technology_id` bigint(20) NOT NULL, PRIMARY KEY (`developer_id`,`technology_id`), KEY `FK_TECHNOLOGY_ID` (`technology_id`), KEY `FK_DEVELOPER_ID` (`developer_id`), CONSTRAINT `FK_DEVELOPER_ID FOREIGN KEY (`developer_id`) REFERENCES `developer` (`id`), CONSTRAINT `FK_TECHNOLOGY_ID` FOREIGN KEY (`technology_id`) REFERENCES `technology` (`id`) );
Use the following code to create the classes:
Source file: Developer.java
@Entity @Table(name = "developer") public class Developer { @Id @GeneratedValue @Column(name = "id") private long id; @Column(name = "name") private String name; @ManyToMany(cascade = CascadeType.ALL) private Set<Technology> technology; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Technology> getTechnology() { return technology; } public void setTechnology(Set<Technology> technology) { this.technology = technology; } @Override public String toString() { return "Developer" + " Id: " + this.id + " Name: " + this.name; } }
@Entity @Table(name = "technology") public class Technology { @Id @GeneratedValue @Column(name = "id") private long id; @Column(name = "language") private String language; @Column(name = "expertise") private String expertise; @ManyToMany(mappedBy = "technology") private Set<Developer> developer; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getLanguage() { return language; } public void setLanguage(String language) { this.language = language; } public String getExpertise() { return expertise; } public void setExpertise(String expertise) { this.expertise = expertise; } public Set<Developer> getDeveloper() { return developer; } public void setDeveloper(Set<Developer> developer) { this.developer = developer; } @Override public String toString() { return "Technology" +" Id: " + this.id +" Language: " + this.language +" Expertise: " + this.expertise; } }
As a part of the scenario, we will create three Developer
objects and two Technology
objects, where all three developers have knowledge on two technologies.
Here, we will insert three Developer
and two Technology
records in to the database. Hibernate will create a mapping between them in a third table. Execute the following code:
Developer developer1= new Developer(); developer1.setName("Vishal"); Developer developer2= new Developer(); developer2.setName("Yogesh"); Developer developer3= new Developer(); developer3.setName("Virendra"); Technology technology1=new Technology(); technology1.setLanguage("Java"); technology1.setExpertise("Intermediate"); Technology technology2=new Technology(); technology2.setLanguage("Bigdata"); technology2.setExpertise("Expert"); Set<Technology> technologies= new HashSet<Technology>(); technologies.add(technology1); technologies.add(technology2); developer1.setTechnology(technologies); developer2.setTechnology(technologies); developer3.setTechnology(technologies); Transaction transaction = session.getTransaction(); transaction.begin(); session.save(developer1); session.save(developer2); session.save(developer3); transaction.commit();
Hibernate: insert into developer (name) values (?) Hibernate: insert into technology (expertise, language) values (?,?) Hibernate: insert into technology (expertise, language) values (?,?) Hibernate: insert into developer (name) values (?) Hibernate: insert into developer (name) values (?) Hibernate: insert into developer_technology (developer_id, technology_id) values (?,?) Hibernate: insert into developer_technology (developer_id, technology_id) values (?,?) Hibernate: insert into developer_technology (developer_id, technology_id) values (?,?) Hibernate: insert into developer_technology (developer_id, technology_id) values (?,?) Hibernate: insert into developer_technology (developer_id, technology_id) values (?,?) Hibernate: insert into developer_technology (developer_id, technology_id) values (?,?)
Here, we will query the Developer
object and then try to get all the Technology
objects that Developer
knows:
Criteria criteria = session.createCriteria(Developer.class); criteria.add(Restrictions.eq("id", 1L)); Developer developer = (Developer) criteria.uniqueResult(); System.out.println(developer.toString()); Set<Technology> tech = developer.getTechnology(); for(Technology technology : tech){ System.out.println(technology.toString()); }
Hibernate: select this_.id as id0_0_, this_.name as name0_0_ from developer this_ where this_.id=? Developer Id: 1 Name: Vishal Hibernate: select technology0_.developer_id as developer1_0_1_, technology0_.technology_id as technology2_1_, technology1_.id as id1_0_, technology1_.expertise as expertise1_0_, technology1_.language as language1_0_ from developer_technology technology0_ inner join technology technology1_ on technology0_.technology_id=technology1_.id where technology0_.developer_id=? Technology Id: 1 Language: Java Expertise: Intermediate Technology Id: 2 Language: Bigdata Expertise: Expert
Now, we will perform a reverse process; from the Technology
object, we will try to get Developers
that have knowledge of that Technology
. Execute the following code:
Criteria criteria = session.createCriteria(Technology.class); criteria.add(Restrictions.eq("id", 1L)); Technology technology= (Technology) criteria.uniqueResult(); System.out.println(technology); Set<Developer> devs = technology.getDeveloper(); for(Developer developer : devs){ System.out.println(developer.toString()); }
Hibernate: select this_.id as id1_0_, this_.expertise as expertise1_0_, this_.language as language1_0_ from technology this_ where this_.id=? Technology Id: 1 Language: Java Expertise: Intermediate Hibernate: select developer0_.technology_id as technology2_1_1_, developer0_.developer_id as developer1_1_, developer1_.id as id0_0_, developer1_.name as name0_0_ from developer_technology developer0_ inner join developer developer1_ on developer0_.developer_id=developer1_.id where developer0_.technology_id=? Developer Id: 2 Name: Yogesh Developer Id: 3 Name: Virendra Developer Id: 1 Name: Vishal
From the output, we can get information on all the knowledge of technology a particular developer has and also of all the developers who have the knowledge of that particular technology. Execute the following code for their respective options:
The option from Developer
:
@ManyToMany(cascade = CascadeType.ALL) private Set<Technology> technology;
We used the @ManyToMany
option; it shows that this particular developer can be associated with multiple technologies.
@ManyToMany(mappedBy="technology") private Set<Developer> developer;
We used the @ManyToMany
option; it shows that this particular technology can be associated with multiple developers. Also, mappedBy="technology"
shows that this is a nonowning side.