目录:
- 概述
- 实体配置
- 单元测试
[一]、概述
本文大概讲述如何注解的方式实现one-to-many many-to-one的双向关联配置以及测试对实体CRUD基本操作,下面的演示以 Author (网络作者 为 one端)、Contact(联系方式 为many端)为例。
[二]、实体配置
Author.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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
package com.micmiu.hibernate.demo.entity; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.persistence.Table; /** * 网络作者 (一对多的一) * * @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-20 上午9:35:14 * @version 1.0 */ @Entity @Table(name = "DEMO_T_AUTHOR") public class Author { private Long id; private String username; private String title; private String sexType; private String description; private List<Contact> contacts = new ArrayList<Contact>(); @Id @Column(name = "ID") @GeneratedValue public Long getId() { return id; } @Column(name = "USERNAME") public String getUsername() { return username; } @Column(name = "TITLE") public String getTitle() { return title; } @OneToMany(cascade = CascadeType.ALL, mappedBy = "author") @OrderBy("id") public List<Contact> getContacts() { return contacts; } @Column(name = "SEX_TYPE") public String getSexType() { return sexType; } @Column(name = "DESCRIPTION") public String getDescription() { return description; } public void setId(Long id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setTitle(String title) { this.title = title; } public void setSexType(String sexType) { this.sexType = sexType; } public void setDescription(String description) { this.description = description; } public void setContacts(List<Contact> contacts) { this.contacts = contacts; } @Override public String toString() { return "Author [id=" + id + ", username=" + username + ", title=" + title + ", sexType=" + sexType + ", description=" + description + "]"; } } |
Contact.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 83 84 85 86 |
package com.micmiu.hibernate.demo.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; /** * 作者{@Author} 的联系方式 一对多的多 * * @author <a href="http://www.micmiu.com">Michael</a> * @time Create on 2013-6-20 上午9:36:16 * @version 1.0 */ @Entity @Table(name = "DEMO_T_CONTACT") public class Contact { private Long id; private String type; private String details; private String other; private Author author; @Id @Column(name = "ID") @GeneratedValue public Long getId() { return id; } @Column(name = "TYPE") public String getType() { return type; } @Column(name = "DETAILS") public String getDetails() { return details; } @Column(name = "OTHER") public String getOther() { return other; } @ManyToOne @JoinColumn(name = "AUTHOR_ID") public Author getAuthor() { return author; } public void setId(Long id) { this.id = id; } public void setAuthor(Author author) { this.author = author; } public void setType(String type) { this.type = type; } public void setDetails(String details) { this.details = details; } public void setOther(String other) { this.other = other; } @Override public String toString() { return "Contact [id=" + id + ", type=" + type + ", details=" + details + ", other=" + other + "]"; } } |
主要关注下代码中 @OneToMany @ManyToOne 两处配置。
[三]、单元测试
测试的类:OneToManyBidirectionalCRUDTest.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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
package com.micmiu.hibernate; import java.util.ArrayList; import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Assert; import org.junit.Test; import com.micmiu.hibernate.demo.entity.Author; import com.micmiu.hibernate.demo.entity.Contact; /** * * 测试 注解配置双向一对多的CRUD * * @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 OneToManyBidirectionalCRUDTest extends AbstractHibernateBaseTest { @Override @Test public void testMethod() { long[] ids = testCreate(); testUpdate(ids); testReadDelete(ids); } public long[] testCreate() { System.out.println(">>>> 测试 添加"); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); int beforeCountAuthor = session.createCriteria(Author.class).list() .size(); int beforeCountContact = session.createCriteria(Contact.class).list() .size(); Author author = new Author(); author.setUsername("test"); author.setTitle("测试人员"); author.setSexType("male"); author.setDescription("测试"); List<Contact> contacts = new ArrayList<Contact>(); Contact c1 = new Contact(); c1.setAuthor(author); c1.setType("blog"); c1.setDetails("http://www.micmiu.com/author/test"); c1.setOther(""); contacts.add(c1); Contact c2 = new Contact(); c2.setAuthor(author); c2.setType("mail"); c2.setDetails("test@micmiu.com"); c2.setOther(""); contacts.add(c2); // 双向1:N N:1 自动持久化关联的数据 author.setContacts(contacts); session.save(author); System.out.println(">>> one id = " + author.getId()); System.out.println(">>> many id = " + c1.getId()); System.out.println(">>> many id = " + c2.getId()); int expectedCountAuthor = session.createCriteria(Author.class).list() .size(); int expectedCountContact = session.createCriteria(Contact.class).list() .size(); Assert.assertEquals(expectedCountAuthor, beforeCountAuthor + 1); Assert.assertEquals(expectedCountContact, beforeCountContact + 2); tx.commit(); session.close(); return new long[] { author.getId(), c1.getId(), c2.getId() }; } public void testUpdate(long[] ids) { System.out.println(">>>> 测试 更新"); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); long authorId = ids[0]; long contactId = ids[1]; long contact2Id = ids[2]; System.out.println(">>>> 更新 1:N中 N的数据"); Contact contact = (Contact) session.get(Contact.class, contactId); System.out.println(contact); contact.setOther("update"); session.update(contact); Contact contact2 = (Contact) session.get(Contact.class, contactId); System.out.println(contact2); Assert.assertEquals("update", contact2.getOther()); System.out.println(">>>> 更新 1:N中 1的数据"); Author author = (Author) session.get(Author.class, authorId); System.out.println(author); author.setDescription("update"); List<Contact> contacts = author.getContacts(); List<Contact> removes = new ArrayList<Contact>(); for (Contact c : contacts) { if (c.getId().longValue() == contact2Id) { removes.add(c); session.delete(c); continue; } } contacts.removeAll(removes); Contact cn = new Contact(); cn.setAuthor(author); cn.setType("blog"); cn.setDetails("http://www.micmiu.com/author/testnew"); cn.setOther("addnew"); contacts.add(cn); author.setContacts(contacts); session.update(author); Author author2 = (Author) session.get(Author.class, authorId); for (Contact c : author2.getContacts()) { System.out.println(c); } Assert.assertEquals("update", author2.getDescription()); tx.commit(); session.close(); } public void testReadDelete(long[] ids) { System.out.println(">>>> 测试读取和删除"); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); System.out.println(">>>> 查询初始"); int beforeCountAuthor = session.createCriteria(Author.class).list() .size(); int beforeCountContact = session.createCriteria(Contact.class).list() .size(); System.out.println(">>>> size one = " + beforeCountAuthor + " many =" + beforeCountContact); long authorId = ids[0]; long contactId = ids[1]; System.out.println(">>>> 查询 1:N中 N的数据"); Contact contact = (Contact) session.get(Contact.class, contactId); System.out.println(contact); Assert.assertEquals(contactId, contact.getId().longValue()); System.out.println(">>>> 删除1:N中 N的数据后,查询N的数据"); session.delete(contact); int actualContactCount2 = session.createCriteria(Contact.class).list() .size(); System.out.println(">>>> size many" + actualContactCount2); Assert.assertEquals(beforeCountContact - 1, actualContactCount2); System.out.println(">>>> 查询 1:N中 1的数据"); Author author = (Author) session.get(Author.class, authorId); System.out.println(author); Assert.assertEquals(authorId, author.getId().longValue()); System.out.println(">>>> 删除1:N中 1的数据后,查询1的数据"); session.delete(author); int actualCountAuthor = session.createCriteria(Author.class).list() .size(); System.out.println(">>>> size one = " + actualCountAuthor); Assert.assertEquals(beforeCountAuthor - 1, actualCountAuthor); System.out.println(">>>> 删除1:N中 1的数据后,查询N的数据"); int actualCountContact = session.createCriteria(Contact.class).list() .size(); Assert.assertEquals(actualCountContact, beforeCountContact - 2); System.out.println(">>>> size many = " + actualCountContact); tx.commit(); session.close(); } } |
AbstractHibernateBaseTest.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 |
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; /** * 单元测试的抽象类 * * @author <a href="http://www.micmiu.com">Michael</a> * @time Create on 2013-6-6 下午7:31:02 * @version 1.0 */ public abstract class AbstractHibernateBaseTest { 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(); } |
运行单元测试,所有测试均通过,详细日志如下:
>>>> 测试 添加
Hibernate:
select
this_.ID as ID2_0_,
this_.DESCRIPTION as DESCRIPT2_2_0_,
this_.SEX_TYPE as SEX3_2_0_,
this_.TITLE as TITLE2_0_,
this_.USERNAME as USERNAME2_0_
from
DEMO_T_AUTHOR this_
Hibernate:
select
this_.ID as ID3_1_,
this_.AUTHOR_ID as AUTHOR5_3_1_,
this_.DETAILS as DETAILS3_1_,
this_.OTHER as OTHER3_1_,
this_.TYPE as TYPE3_1_,
author2_.ID as ID2_0_,
author2_.DESCRIPTION as DESCRIPT2_2_0_,
author2_.SEX_TYPE as SEX3_2_0_,
author2_.TITLE as TITLE2_0_,
author2_.USERNAME as USERNAME2_0_
from
DEMO_T_CONTACT this_
left outer join
DEMO_T_AUTHOR author2_
on this_.AUTHOR_ID=author2_.ID
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
select
hibernate_sequence.nextval
from
dual
>>> one id = 75
>>> many id = 76
>>> many id = 77
Hibernate:
insert
into
DEMO_T_AUTHOR
(DESCRIPTION, SEX_TYPE, TITLE, USERNAME, ID)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
DEMO_T_CONTACT
(AUTHOR_ID, DETAILS, OTHER, TYPE, ID)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
DEMO_T_CONTACT
(AUTHOR_ID, DETAILS, OTHER, TYPE, ID)
values
(?, ?, ?, ?, ?)
Hibernate:
select
this_.ID as ID2_0_,
this_.DESCRIPTION as DESCRIPT2_2_0_,
this_.SEX_TYPE as SEX3_2_0_,
this_.TITLE as TITLE2_0_,
this_.USERNAME as USERNAME2_0_
from
DEMO_T_AUTHOR this_
Hibernate:
select
this_.ID as ID3_1_,
this_.AUTHOR_ID as AUTHOR5_3_1_,
this_.DETAILS as DETAILS3_1_,
this_.OTHER as OTHER3_1_,
this_.TYPE as TYPE3_1_,
author2_.ID as ID2_0_,
author2_.DESCRIPTION as DESCRIPT2_2_0_,
author2_.SEX_TYPE as SEX3_2_0_,
author2_.TITLE as TITLE2_0_,
author2_.USERNAME as USERNAME2_0_
from
DEMO_T_CONTACT this_
left outer join
DEMO_T_AUTHOR author2_
on this_.AUTHOR_ID=author2_.ID
>>>> 测试 更新
>>>> 更新 1:N中 N的数据
Hibernate:
select
contact0_.ID as ID3_1_,
contact0_.AUTHOR_ID as AUTHOR5_3_1_,
contact0_.DETAILS as DETAILS3_1_,
contact0_.OTHER as OTHER3_1_,
contact0_.TYPE as TYPE3_1_,
author1_.ID as ID2_0_,
author1_.DESCRIPTION as DESCRIPT2_2_0_,
author1_.SEX_TYPE as SEX3_2_0_,
author1_.TITLE as TITLE2_0_,
author1_.USERNAME as USERNAME2_0_
from
DEMO_T_CONTACT contact0_
left outer join
DEMO_T_AUTHOR author1_
on contact0_.AUTHOR_ID=author1_.ID
where
contact0_.ID=?
Contact [id=76, type=blog, details=http://www.micmiu.com/author/test, other=null]
Contact [id=76, type=blog, details=http://www.micmiu.com/author/test, other=update]
>>>> 更新 1:N中 1的数据
Author [id=75, username=test, title=测试人员, sexType=male, description=测试]
Hibernate:
select
contacts0_.AUTHOR_ID as AUTHOR5_2_1_,
contacts0_.ID as ID3_1_,
contacts0_.ID as ID3_0_,
contacts0_.AUTHOR_ID as AUTHOR5_3_0_,
contacts0_.DETAILS as DETAILS3_0_,
contacts0_.OTHER as OTHER3_0_,
contacts0_.TYPE as TYPE3_0_
from
DEMO_T_CONTACT contacts0_
where
contacts0_.AUTHOR_ID=?
order by
contacts0_.ID
Contact [id=76, type=blog, details=http://www.micmiu.com/author/test, other=update]
Contact [id=null, type=blog, details=http://www.micmiu.com/author/testnew, other=addnew]
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
insert
into
DEMO_T_CONTACT
(AUTHOR_ID, DETAILS, OTHER, TYPE, ID)
values
(?, ?, ?, ?, ?)
Hibernate:
update
DEMO_T_AUTHOR
set
DESCRIPTION=?,
SEX_TYPE=?,
TITLE=?,
USERNAME=?
where
ID=?
Hibernate:
update
DEMO_T_CONTACT
set
AUTHOR_ID=?,
DETAILS=?,
OTHER=?,
TYPE=?
where
ID=?
Hibernate:
delete
from
DEMO_T_CONTACT
where
ID=?
>>>> 测试读取和删除
>>>> 查询初始
Hibernate:
select
this_.ID as ID2_0_,
this_.DESCRIPTION as DESCRIPT2_2_0_,
this_.SEX_TYPE as SEX3_2_0_,
this_.TITLE as TITLE2_0_,
this_.USERNAME as USERNAME2_0_
from
DEMO_T_AUTHOR this_
Hibernate:
select
this_.ID as ID3_1_,
this_.AUTHOR_ID as AUTHOR5_3_1_,
this_.DETAILS as DETAILS3_1_,
this_.OTHER as OTHER3_1_,
this_.TYPE as TYPE3_1_,
author2_.ID as ID2_0_,
author2_.DESCRIPTION as DESCRIPT2_2_0_,
author2_.SEX_TYPE as SEX3_2_0_,
author2_.TITLE as TITLE2_0_,
author2_.USERNAME as USERNAME2_0_
from
DEMO_T_CONTACT this_
left outer join
DEMO_T_AUTHOR author2_
on this_.AUTHOR_ID=author2_.ID
>>>> size one = 4 many =10
>>>> 查询 1:N中 N的数据
Contact [id=76, type=blog, details=http://www.micmiu.com/author/test, other=update]
>>>> 删除1:N中 N的数据后,查询N的数据
Hibernate:
delete
from
DEMO_T_CONTACT
where
ID=?
Hibernate:
select
this_.ID as ID3_1_,
this_.AUTHOR_ID as AUTHOR5_3_1_,
this_.DETAILS as DETAILS3_1_,
this_.OTHER as OTHER3_1_,
this_.TYPE as TYPE3_1_,
author2_.ID as ID2_0_,
author2_.DESCRIPTION as DESCRIPT2_2_0_,
author2_.SEX_TYPE as SEX3_2_0_,
author2_.TITLE as TITLE2_0_,
author2_.USERNAME as USERNAME2_0_
from
DEMO_T_CONTACT this_
left outer join
DEMO_T_AUTHOR author2_
on this_.AUTHOR_ID=author2_.ID
>>>> size many9
>>>> 查询 1:N中 1的数据
Author [id=75, username=test, title=测试人员, sexType=male, description=update]
>>>> 删除1:N中 1的数据后,查询1的数据
Hibernate:
select
contacts0_.AUTHOR_ID as AUTHOR5_2_1_,
contacts0_.ID as ID3_1_,
contacts0_.ID as ID3_0_,
contacts0_.AUTHOR_ID as AUTHOR5_3_0_,
contacts0_.DETAILS as DETAILS3_0_,
contacts0_.OTHER as OTHER3_0_,
contacts0_.TYPE as TYPE3_0_
from
DEMO_T_CONTACT contacts0_
where
contacts0_.AUTHOR_ID=?
order by
contacts0_.ID
Hibernate:
delete
from
DEMO_T_CONTACT
where
ID=?
Hibernate:
delete
from
DEMO_T_AUTHOR
where
ID=?
Hibernate:
select
this_.ID as ID2_0_,
this_.DESCRIPTION as DESCRIPT2_2_0_,
this_.SEX_TYPE as SEX3_2_0_,
this_.TITLE as TITLE2_0_,
this_.USERNAME as USERNAME2_0_
from
DEMO_T_AUTHOR this_
>>>> size one = 3
>>>> 删除1:N中 1的数据后,查询N的数据
Hibernate:
select
this_.ID as ID3_1_,
this_.AUTHOR_ID as AUTHOR5_3_1_,
this_.DETAILS as DETAILS3_1_,
this_.OTHER as OTHER3_1_,
this_.TYPE as TYPE3_1_,
author2_.ID as ID2_0_,
author2_.DESCRIPTION as DESCRIPT2_2_0_,
author2_.SEX_TYPE as SEX3_2_0_,
author2_.TITLE as TITLE2_0_,
author2_.USERNAME as USERNAME2_0_
from
DEMO_T_CONTACT this_
left outer join
DEMO_T_AUTHOR author2_
on this_.AUTHOR_ID=author2_.ID
>>>> size many = 8
本文介绍到此结束@Michael Sun.
😳 我想知道一个实体类里面可不可以有多个onetoMany
可以个