1. 程式人生 > >hibernate多對多關係配置--增刪改查

hibernate多對多關係配置--增刪改查

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();
	}
}