目录:
- 应用场景
- 演示
[一]、应用场景
在用注解的方式(@ManyToMany @JoinTable)实现多对多映射时,并没有具体的多对多关系表的实体类,那么我们如何利用HQL实现关联查询呢?比如:学生和课程表之间的多对多关系。
[二]、演示
1.实体类
IdEntity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package com.micmiu.hibernate.anno.entity; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.MappedSuperclass; /** * 统一定义id的entity基类. * * 基类统一定义id的属性名称、数据类型、列名映射及生成策略. <br> * 子类可重载getId()函数重定义id的列名映射和生成策略. * * @author <a href="http://www.micmiu.com">Michael Sun</a> */ @MappedSuperclass public abstract class IdEntity { protected Long id; @Id @Column(name = "ID") @GeneratedValue // @GeneratedValue(strategy = GenerationType.SEQUENCE) // @GeneratedValue(generator = "system-uuid") // @GenericGenerator(name = "system-uuid", strategy = "uuid") public Long getId() { return id; } public void setId(Long id) { this.id = id; } } |
学生实体类:Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
package com.micmiu.hibernate.anno.entity; import java.util.Collection; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.OrderBy; import javax.persistence.Table; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; /** * * Description: * * @author <a href="http://www.micmiu.com">Michael</a> * @see <a href="http://www.micmiu.com">http://www.micmiu.com</a> * @time Create on 2013-6-6 下午2:40:08 * @version 1.0 */ @Entity @Table(name = "DEMO_T_STUDENT") public class Student extends IdEntity { @Column(name = "NAME") private String name; @Column(name = "BIRTHDAY") private Date birthday; private Collection<Course> courses; public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @ManyToMany @JoinTable(name = "DEMO_R_S2C", joinColumns = { @JoinColumn(name = "SID") }, inverseJoinColumns = { @JoinColumn(name = "CID") }) @Fetch(FetchMode.SUBSELECT) @OrderBy("id") public Collection<Course> getCourses() { return courses; } public void setCourses(Collection<Course> courses) { this.courses = courses; } @Override public String toString() { return "Student [name=" + name + ", birthday=" + birthday + "]"; } } |
课程实体类:Course.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package com.micmiu.hibernate.anno.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; /** * * Description: * * @author <a href="http://www.micmiu.com">Michael</a> * @see <a href="http://www.micmiu.com">http://www.micmiu.com</a> * @time Create on 2013-6-6 下午2:52:31 * @version 1.0 */ @Entity @Table(name = "DEMO_T_COURSE") public class Course extends IdEntity { @Column(name = "NAME") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Course [name=" + name + "]"; } } |
2.初始化数据:
利用dbunit初始化演示数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version='1.0' encoding="utf-8"?> <dataset> <demo_t_student id="101" name="micmiu.com" birthday="2012-12-12" /> <demo_t_student id="102" name="sjsky007@gmail.com" birthday="2008-08-08" /> <demo_t_student id="103" name="ctosun.com" birthday="2013-01-04" /> <demo_t_course id="901" name="chinese" /> <demo_t_course id="902" name="english" /> <demo_t_course id="903" name="math" /> <demo_r_s2c sid="101" cid="901" /> <demo_r_s2c sid="101" cid="902" /> <demo_r_s2c sid="101" cid="903" /> <demo_r_s2c sid="102" cid="902" /> <demo_r_s2c sid="102" cid="903" /> <demo_r_s2c sid="103" cid="903" /> </dataset> |
3.演示关联查询
在Student中配置了多对多关系,在Course没有配置多对多关系,下面将分别演示关联查询这两个实体的方法:
测试基础类 HibernateBaseTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package com.micmiu.hibernate; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; /** * * Description: * * @author <a href="http://www.micmiu.com">Michael</a> * @see <a href="http://www.micmiu.com">http://www.micmiu.com</a> * @time Create on 2013-6-6 下午7:31:02 * @version 1.0 */ public abstract class HibernateBaseTest { protected static SessionFactory sessionFactory; @BeforeClass public static void beforeClass() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); } @AfterClass public static void afterClass() { sessionFactory.close(); } @Test public abstract void testMethod(); } |
测试HQL查询:ManyToManyTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
package com.micmiu.hibernate; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.junit.Assert; import org.junit.Test; import com.micmiu.hibernate.anno.entity.Course; import com.micmiu.hibernate.anno.entity.Student; /** * * Description:测试 注解配置多对多关系的表之间的联合查询 * * @author <a href="http://www.micmiu.com">Michael</a> * @see <a href="http://www.micmiu.com">http://www.micmiu.com</a> * @time Create on 2013-6-7 上午11:38:49 * @version 1.0 */ public class ManyToManyTest extends HibernateBaseTest { @Override @Test public void testMethod() { // 测试查询有配置多对多关系的对象 test1(); // 测试查询无配置多对多关系的对象 test2(); } /** * 测试查询有配置多对多关系的对象 */ @SuppressWarnings("unchecked") public void test1() { Session session = sessionFactory.openSession(); session.beginTransaction(); String hql = "select s from Student s join s.courses c where s.name like '%micmiu.com%' and c.name ='math'"; String hql2 = "select s from Student s,Course c where c.id in elements (s.courses) and s.name like '%micmiu.com%' and c.name ='math'"; Query query = session.createQuery(hql); List<Student> list = query.list(); System.out.println("----------- size:" + list.size()); Assert.assertEquals(1, list.size()); for (Student s : list) { Assert.assertEquals("micmiu.com", s.getName()); System.out.println(s); } session.getTransaction().commit(); session.close(); } /** * 测试查询无配置多对多关系的对象 */ @SuppressWarnings("unchecked") public void test2() { Session session = sessionFactory.openSession(); session.beginTransaction(); String hql = "select distinct c from Student s,Course c where c.id in elements (s.courses) and s.name like '%micmiu.com%' and c.name ='math'"; Query query = session.createQuery(hql); List<Course> list = query.list(); System.out.println("----------- size:" + list.size()); Assert.assertEquals(1, list.size()); for (Course c : list) { Assert.assertEquals("math", c.getName()); System.out.println(c); } session.getTransaction().commit(); session.close(); } } |
执行结果:单元测试通过,运行日志如下:
Hibernate:
select
student0_.ID as ID1_,
student0_.birthday as birthday1_,
student0_.name as name1_
from
DEMO_T_STUDENT student0_
inner join
DEMO_R_S2C courses1_
on student0_.ID=courses1_.SID
inner join
DEMO_T_COURSE course2_
on courses1_.CID=course2_.ID
where
(
student0_.name like ‘%micmiu.com%’
)
and course2_.name=’math’
———– size:1
Student [name=micmiu.com, birthday=2012-12-12 00:00:00.0]
Hibernate:
select
distinct course1_.ID as ID0_,
course1_.name as name0_
from
DEMO_T_STUDENT student0_ cross
join
DEMO_T_COURSE course1_
where
(
course1_.ID in (
select
courses2_.CID
from
DEMO_R_S2C courses2_
where
student0_.ID=courses2_.SID
)
)
and (
student0_.name like ‘%micmiu.com%’
)
and course1_.name=’math’
———– size:1
Course [name=math]
本文介绍到此结束@Michael Sun.
原创文章,转载请注明: 转载自micmiu – 软件开发+生活点滴[ http://www.micmiu.com/ ]
本文链接地址: http://www.micmiu.com/j2ee/hibernate/hql-manytomany-query/
0 条评论。