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