hibernate多對多關係配置--增刪改查
阿新 • • 發佈:2019-01-11
hibernate多對多關聯配置--並實現增刪改查
hibernate就不多介紹了,這裡就直接上我專案中使用的例子做說明。
資料模型
這是專案中使用者和使用者組的資料模型er圖草稿,具體的model物件欄位就以專案中的為主了。
model類以及pojo介面,這裡pojo介面用不上,大家測試的時候也可以去掉
package com.supre.model; import java.io.Serializable; import java.util.Set; public class User { private int userId; private String userNo; private String userName; private String password; private String telephone; private String remark; private int userStatus; private Set<Group> groups; public User() { super(); // TODO Auto-generated constructor stub } public User(int userId, String userNo) { super(); this.userId = userId; this.userNo = userNo; } public User(int userId, String userNo, String userName, String password, String telephone, String remark, int userStatus, Set<Group> groups) { super(); this.userId = userId; this.userNo = userNo; this.userName = userName; this.password = password; this.telephone = telephone; this.remark = remark; this.userStatus = userStatus; this.groups = groups; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getUserNo() { return userNo; } public void setUserNo(String userNo) { this.userNo = userNo; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } public Set<Group> getGroups() { return groups; } public void setGroups(Set<Group> groups) { this.groups = groups; } @Override public String toString() { return "User [userId=" + userId + ", userNo=" + userNo + ", userName=" + userName + ", password=" + password + ", telephone=" + telephone + ", remark=" + remark + ", userStatus=" + userStatus + ", groupSize=" + groups.size() + "]"; } }
package com.supre.model; import java.io.Serializable; import java.util.Date; import java.util.Set; public class Group{ private int groupId; private String groupName; private Date createTime; private String remark; //private User user; //負責人 private Set<User> users; public Group() { super(); // TODO Auto-generated constructor stub } public int getGroupId() { return groupId; } public void setGroupId(int groupId) { this.groupId = groupId; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public Set<User> getUsers() { return users; } public void setUsers(Set<User> users) { this.users = users; } public Group(int groupId, String groupName, Date createTime, String remark, Set<User> users) { super(); this.groupId = groupId; this.groupName = groupName; this.createTime = createTime; this.remark = remark; this.users = users; } @Override public String toString() { return "Group [groupId=" + groupId + ", groupName=" + groupName + ", createTime=" + createTime + ", remark=" + remark + ", userSize=" + users.size() + "]"; } }
hibernate的配置資訊
這裡專案中使用的xml配置 hibernate主配置檔案:hibernate.xml 配置資料庫連線資訊
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/idisk?useUnicode=true&characterEncoding=utf-8</property> <property name="connection.username">root</property> <property name="connection.password">supre2015</property> <property name="show_sql">true</property> <mapping resource="hibernate/user.hbm.xml"/> <mapping resource="hibernate/group.hbm.xml"/> </session-factory> </hibernate-configuration>
Model類User的對映檔案
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.supre.model">
<class name="User" table="tb_user">
<id name="userId" column="user_id">
<generator class="native"></generator>
</id>
<property name="userNo" column="user_no"></property>
<property name="userName" column="user_name"></property>
<property name="password" column="password"></property>
<property name="telephone" column="telephone"></property>
<property name="remark" column="remark"></property>
<property name="userStatus" column="user_status"></property>
<set name="groups" table="user_group" inverse="true" cascade="none" lazy="false">
<key column="user_id"></key>
<many-to-many class="Group" column="group_id" ></many-to-many>
</set>
</class>
</hibernate-mapping>
Model類Group的對映檔案
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.supre.model">
<class name="Group" table="tb_group">
<id name="groupId" column="group_id">
<generator class="native"></generator>
</id>
<property name="groupName" column="group_name"></property>
<property name="createTime" column="create_time"></property>
<property name="remark" column="remark"></property>
<!-- <many-to-one name="user" class="User" column="user_id" lazy="false"></many-to-one> -->
<set name="users" table="user_group" inverse="false" cascade="none" lazy="false">
<key column="group_id"></key>
<many-to-many class="User" column="user_id" lazy="false"></many-to-many>
</set>
</class>
</hibernate-mapping>
hibernate的幫助類
package com.supre.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateSessionFactory {
private static SessionFactory factory;
private static Configuration cfg;
private static ThreadLocal<Session> local = new ThreadLocal<Session>();
static {
cfg = new Configuration().configure("hibernate.xml");
factory = cfg.buildSessionFactory();
}
public static void buildSessionFactory() {
cfg = new Configuration().configure("hibernate.xml");
factory = cfg.buildSessionFactory();
}
private HibernateSessionFactory(){};
public static SessionFactory getSessionFactory(){
return factory;
}
public static Session getSession(){
Session session=local.get();
if(session==null || !session.isOpen()){
if(factory==null){
buildSessionFactory();
}
session = factory.openSession();
local.set(session);
}
return session;
}
public static void closeSession(){
Session session=local.get();
if(session!=null && session.isOpen()){
session.close();
}
local.set(null);
}
}
下面是測試類,
package com.supre.util;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Session;
import com.supre.model.Group;
import com.supre.model.User;
public class TestHibernate {
public static void main(String[] args) {
// testAddGroup();
// testAddUser();
// testAddGroup2();
// testAddUser2();
// testAddUser3();
// testSelect();
// testDeleteUser();
testDeleteGroup();
}
//測試新增簡單主控方物件(Group)
public static void testAddGroup(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
Group g = new Group();
g.setGroupName("分組1");
s.save(g);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
//測試新增簡單被控方物件(User)
public static void testAddUser(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
User u = new User();
u.setUserName("使用者1");
s.save(u);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
//測試新增主控方物件(Group)以及對應關係
/**
* 如果主控方(group.hbm.xml)
* 配置cascade=‘save-update’,則在下述結果中會修改被控方(User)資料
* 配置cascade=‘none’,則在下述結果不會修改被控方(User)資料
*/
public static void testAddGroup2(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
User u = new User();
u.setUserId(3);//資料庫中已有的使用者id
User u1 = new User();
u1.setUserId(4);//資料庫中已有的使用者id
Group g = new Group();
g.setGroupName("分組4");
Set<User> us = new HashSet<>();
us.add(u);
us.add(u1);
g.setUsers(us);
s.save(g);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
//測試新增被控方物件(User)以及對應關係
/**
*這裡被控方和主控方都配置cascade="none"
*
* 如下程式碼中,無法實現將關係新增到user_group表中,
* 相反會刪掉g和g1在user_group中的全部關係,
* 因為g和g1中的users全部為空的
*/
public static void testAddUser2(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
User u = new User();
u.setUserName("使用者4");
Group g = new Group();
g.setGroupId(6);//資料庫中已有的使用者id
Group g1 = new Group();
g1.setGroupId(8);//資料庫中已有的使用者id
Set<Group> gs = new HashSet<>();
gs.add(g);
gs.add(g1);
u.setGroups(gs);
s.save(u);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
//測試新增被控方物件(User)以及對應關係
/**
* 這裡被控方和主控方都配置cascade="none"
*
* 因為Group是主控方(維護關係方),在新增或者修改關係時,
* 必須由Group方來控制,下面程式碼中的1和2兩處是必須的,
* 如果沒有下面1和2兩行程式碼,則只會簡單的新增User資料,
* 不寫將關係寫到user_group表中
*/
public static void testAddUser3(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
User u = new User();
u.setUserName("使用者8");
Group g = (Group) s.get(Group.class, 9);
Group g1 = (Group) s.get(Group.class, 10);
Set<Group> gs = new HashSet<>();
g.getUsers().add(u); // ----1
g1.getUsers().add(u); // -----2
gs.add(g);
gs.add(g1);
u.setGroups(gs);
s.save(u);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
/**
* update和save方法大致一樣,不過要注意主控方(Group)執行update方法前,
* 必須先將原Group中的users取到,再進行修改,這樣才能保證修改時能準確的維護關係
* 如果是修改關係,則通過修改Group中的users來修改關係
*/
public static void testUpdate(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
Group g = (Group) s.get(Group.class, 9);
g.setGroupName("管理員");
//g.getUsers().remove(new User(7, ""));
s.save(g);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
/**
* 這裡被控方和主控方都配置cascade="none"
* 如果主控方group.hbm.xml中配置的cascade="delete"或者cascade="all"
* 則刪除的時候會級聯刪除掉User
*/
public static void testDeleteGroup(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
//刪除指定的User以及關係
Group g = (Group) s.get(Group.class, 9);
User u = (User) s.get(User.class, 7);
g.getUsers().remove(u);//刪除關係需要先把users中的相應的user移除掉
s.delete(g);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
/**
* 這裡被控方和主控方都配置cascade="none"
* 這裡如果需要刪除關係還是需要先獲得主控方,通過主控方來維護關係
*/
public static void testDeleteUser(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
//刪除指定的User以及關係
User u = (User) s.get(User.class, 12);
Set<Group> gs = u.getGroups();
for (Group g : gs) {
g.getUsers().remove(u); //如果需要刪除關係就需要此操作
}
s.delete(u);
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
/**
* 這裡查詢不分主控方和被控方
* 配置查詢載入方式
* lazy="false" 不使用懶載入,查詢時直接載入關聯資料
* lazy="true" 支援懶載入,只有在用到關聯資料時再去執行查詢
* 支援懶載入需要注意:在用到關聯資料時只能在一個事務內(即一個數據庫session內)
* 如果事務外使用到該資料,程式則會報資料庫連線異常,因為在事務外執行查詢時,session已經關閉。
* 這裡要根據自己專案中需要來採取最佳配置
*/
public static void testSelect(){
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
List<Group> gs = s.createQuery("from Group").list();
for (Group g : gs) {
/**
* 這裡還需要注意,這裡列印物件時不能使用預設的toString()方法
* 因為預設的toString()方法中對Set集合的處理是直接呼叫Set集合中每個物件的toString()
* 如果Group物件中有User值,則在會出現Group.toString() 中呼叫Set中的 User.toString()
* 而User.toString()中則會掉用Set中的Group.toString()方法,而出現死迴圈而導致記憶體溢位異常
*/
System.out.println(g);//
}
Set<User> us = gs.get(3).getUsers();
for (User user : us) {
System.out.println(user);
}
List<User> users = s.createQuery("from User").list();
for (User u : users) {
System.out.println(u);
}
s.flush();
s.getTransaction().commit();
s.clear();
s.close();
}
}