一.先上知識點:
1.hibernate多對多關聯關系中最重要的參數是(基於配置文件xxx.hbm.xml文件形式):
1):inverse屬性,如果設置inverse=“true”就代表讓對方參與維護第三方表格。//這個屬性特別重要,多對多關系中最好有且只有一個維護第三方表格,如果兩方都維護第三方表格,那么可能第三方表格會重復維護現象(有可能會造成第三方表格聯合主鍵的重復)
2):lazy屬性,這個屬性代表延遲加載與否,在講這個屬性之前,先講一個東西,就是在hibernate多對多關聯關系中,在雙方的類中都會出現一個Set<XXX>這個集合屬性(在讀取過程中,這個set集合會被hibernate封裝成persistentSet集合),當在xxx.hbm.xml文件中設置lazy=“false”時,就說明,不會讓延遲加載起作用,那么這個延遲加載加載什么東西呢?延遲加載的東西就是剛剛提到的Set<XXX>集合中的東西,打個比方,現在有多對多的User類和Educate類(員工多對多培訓課程),在User類中的java代碼如下:
package com.ssh.entities; import java.io.Serializable; import java.util.Date; import java.util.HashSet; import java.util.Set; public class User { private Long id;//員工編號 private String name;//員工用戶名 private String password;//登錄密碼 private Byte sex;//性別 private Date birthday;//生日 private Date createtime;//創建時間 private Byte isadmin;//是否為管理員 private String content;//人員簡介 private Set<Educate> educate=new HashSet<Educate>(); public Set<Educate> getEducate() { return educate; } public void setEducate(Set<Educate> educate) { this.educate = educate; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Byte getSex() { return sex; } public void setSex(Byte sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public Byte getIsadmin() { return isadmin; } public void setIsadmin(Byte isadmin) { this.isadmin = isadmin; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public User(Long id, String name, String password, Byte sex, Date birthday, Date createtime, Byte isadmin, String content) { this.id = id; this.name = name; this.password = password; this.sex = sex; this.birthday = birthday; this.createtime = createtime; this.isadmin = isadmin; this.content = content; } public User() { } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", password=" + password + ", sex=" + sex + ", birthday=" + birthday + ", createtime=" + createtime + ", isadmin=" + isadmin + ", content=" + content + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }
上述代碼中標紅的就是一個Set<Educate>集合。
那我在User.hbm.xml文件中配置lazy="false"的時候,就是說明,當我前端或者后台需要加載user對象時,那這個帶有對方(Educate類)的集合也會通過第三方表格順帶着把Educate類中的信息一起加載出來,
反之,當lazy="true"的時候就默認lazy延遲加載工程開啟,也就是說Set集合中的東西,現在不會給加載出來。
3)cascade屬性,我在項目中一般配置 cascade=“all”,這個就代表在級聯操作時(保存、刪除)會不會級聯到關聯的一方
總結:基於配置文件的hibernate 多對多就是lazy和inverse屬性在起關鍵作用。
2.hibernate 多對多中的級聯保存和刪除:
1)保存,保存一般情況下不僅保存自己一方的對象到數據庫,還需要順帶着把和另一方的關系也保存到第三方表格,那么這時,如果是自己這方是負責維護第三方表格的,那么當編輯自己對象的信息時(將集合中塞入對方對象到集合中,代表與對方的關系),在執行hibernate的session的saveOrupdate()方法時,不僅保存自己對象到數據庫中,同時也會把維護關系保存到第三方表格中,如果自己這方沒有負責維護第三方表格,那么即便自己這方的Set集合中添加了對方對象的信息,當執行hibernate的session的 saveorUpdate()方法時,只能是把自己的信息保存到自己對應的數據庫中,與對方的關系(通過set集合中的信息進行設置,通過第三方的數據表格體現)的第三方表格,沒有發生更新,也就是說沒有達到想要的結果。
現在舉例說明一下:
User類(如上)和User.hbm.xml文件:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.ssh.entities.User" table="user"> <id column="id" name="id" type="java.lang.Long"> <generator class="native"></generator> </id> <property name="name" length="50" type="java.lang.String"/> <property name="password" length="50" type="java.lang.String"/> <property name="sex" length="4" type="java.lang.Byte"/> <property name="birthday" length="23" type="java.util.Date"/> <property name="createtime" length="23" type="java.util.Date"/> <property name="isadmin" length="4" type="java.lang.Byte"/> <property name="content" length="2000" type="java.lang.String"/> <set name="educate" table="user_educate" lazy="false" cascade="all" inverse="false"> <key column="user_id"></key> <many-to-many class="com.ssh.entities.Educate" column="educate_id"></many-to-many> </set> </class> </hibernate-mapping>
Educate類和Educate.hbm.xml
package com.ssh.entities; import java.io.Serializable; import java.util.Date; import java.util.HashSet; import java.util.Set; public class Educate { private Long id;//培訓標號 private String name;//培訓名稱 private String purpose;//培訓目的 private Date begintime;//培訓開始時間 private Date endtime;//培訓結束時間 private String datum;//培訓材料 private String teacher;//培訓講師 private String student;//培訓人員 private Date createtime;//創建時間 private Byte educate;//培訓是否完成 private String effect;//培訓效果 private String summarize;//培訓總結 private Set<User> user=new HashSet<User>(); public Set<User> getUser() { return user; } public void setUser(Set<User> user) { this.user = user; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPurpose() { return purpose; } public void setPurpose(String purpose) { this.purpose = purpose; } public Date getBegintime() { return begintime; } public void setBegintime(Date begintime) { this.begintime = begintime; } public Date getEndtime() { return endtime; } public void setEndtime(Date endtime) { this.endtime = endtime; } public String getDatum() { return datum; } public void setDatum(String datum) { this.datum = datum; } public String getTeacher() { return teacher; } public void setTeacher(String teacher) { this.teacher = teacher; } public String getStudent() { return student; } public void setStudent(String student) { this.student = student; } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public Byte getEducate() { return educate; } public void setEducate(Byte educate) { this.educate = educate; } public String getEffect() { return effect; } public void setEffect(String effect) { this.effect = effect; } public String getSummarize() { return summarize; } public void setSummarize(String summarize) { this.summarize = summarize; } public Educate(Long id, String name, String purpose, Date begintime, Date endtime, String datum, String teacher, String student, Date createtime, Byte educate, String effect, String summarize) { this.id = id; this.name = name; this.purpose = purpose; this.begintime = begintime; this.endtime = endtime; this.datum = datum; this.teacher = teacher; this.student = student; this.createtime = createtime; this.educate = educate; this.effect = effect; this.summarize = summarize; } public Educate() { } @Override public String toString() { return "Educate [id=" + id + ", name=" + name + ", purpose=" + purpose + ", begintime=" + begintime + ", endtime=" + endtime + ", datum=" + datum + ", teacher=" + teacher + ", student=" + student + ", createtime=" + createtime + ", educate=" + educate + ", effect=" + effect + ", summarize=" + summarize + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Educate other = (Educate) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.ssh.entities.Educate" table="educate"> <id column="id" name="id" type="java.lang.Long"> <generator class="native"></generator> </id> <property name="name" length="100" type="java.lang.String"></property> <property name="purpose" length="500" type="java.lang.String"/> <property name="begintime" length="23" type="java.util.Date"/> <property name="endtime" length="23" type="java.util.Date"/> <property name="datum" length="2000" type="java.lang.String"/> <property name="teacher" length="50" type="java.lang.String"/> <property name="student" length="50" type="java.lang.String"/> <property name="createtime" length="23" type="java.util.Date"/> <property name="effect" length="500" type="java.lang.String"/> <property name="educate" length="1" type="java.lang.Byte"/> <property name="summarize" length="2000" type="java.lang.String"/> <set name="user" table="user_educate" lazy="true" cascade="all" inverse="true"> <key column="educate_id"></key> <many-to-many class="com.ssh.entities.User" column="user_id"></many-to-many> </set> </class> </hibernate-mapping>
后台控制的java代碼(保存和另一方關系的代碼):
public String insertcourse(){ String[] para=request.getParameterValues("edupara"); String userid=request.getParameter("userid"); if(para.length>0){ User us=userService.getUser(Long.parseLong(userid)); Set<Educate> edus=new HashSet<Educate>(); edus=us.getEducate(); for(String str: para ){ Educate educate=educateService.getForEdu(Long.parseLong(str)); /* Set users=new HashSet<User>(); users=educate.getUser(); System.out.println(users.size()); users.add(us); System.out.println(users.size()); educate.setUser(users); educateService.saveorUpdate(educate); */ edus.add(educate); } us.setEducate(edus); userService.saveOrUpdate(us); } return "insertcourse";
2)刪除級聯的注意事項:
(1)如果不是User維持關聯關系:
——若連接表user_educate中有參照user表中該記錄的記錄(即在user_educate表中存在user_id的記錄)時,則刪除失敗。
——若連接表user_educate中沒有參照user表中該記錄的記錄時,則可以成功地將該記錄刪除。
(2)如果是User維持關聯關系:
——先將連接表user_educate中參照user表中該記錄的記錄刪除,然后將該學生記錄從user表中刪除
最后附上后台處理的完整代碼:
UserAction.java
package com.ssh.action; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; import com.ssh.entities.Educate; import com.ssh.entities.User; import com.ssh.service.EducateService; import com.ssh.service.UserService; public class HumanAction extends ActionSupport implements ServletRequestAware{ /** * @author zhangshitong */ private static final long serialVersionUID = 1L; private String username; private String password; private UserService userService; private InputStream inputStream; private HttpServletRequest request; private Long id; private List<Educate> eduList; private List<User> userList; private EducateService educateService; private User userForEdit; public void setEducateService(EducateService educateService) { this.educateService = educateService; } public void setId(Long id) { this.id = id; } private User user; public void setUser(User user) { this.user = user; } public User getUser() { return user; } public InputStream getInputStream() { return inputStream; } public void setUserService(UserService userService) { this.userService = userService; } 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 adduser(){ user.setCreatetime(new Date()); //user.setId(null); System.out.println(user); userService.saveOrUpdate(user); user = null; return "add"; } public String list(){ System.out.println(userService.getForList()); request.setAttribute("user", userService.getForList()); return "list"; } public String select(){ User usertemp=userService.getUser(id); this.userForEdit=usertemp; request.setAttribute("signalUser", usertemp); return "edit"; } public String delete(){ userService.deleteUser(id); try { inputStream = new ByteArrayInputStream("1".getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block try { inputStream = new ByteArrayInputStream("0".getBytes("UTF-8")); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); } return "ajax-success"; } public String modify(){ user.setEducate(userForEdit.getEducate()); user.setCreatetime(new Date()); System.out.println(user); userService.saveOrUpdate(user); return "modified"; } public String login(){ User user=userService.validName(username); if(user==null){ try { inputStream = new ByteArrayInputStream("3".getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ if(user.getPassword().equals(password)){ try {request.getSession().setAttribute("user", user); inputStream = new ByteArrayInputStream("1".getBytes("UTF-8")); //ctx.getSession().put("user", user); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }else{ try { inputStream = new ByteArrayInputStream("0".getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return "ajax-success"; } public String userselecteducate(){ System.out.println("這是查看員工選擇課程時員工的id值:"+id); Set eduSet=userService.getEducateInUser(id); //System.out.println(eduSet); List<Educate> eduList=new ArrayList<Educate>(); Iterator it=eduSet.iterator(); while(it.hasNext()){ Educate eduTemp=(Educate) it.next(); eduList.add(eduTemp); } request.setAttribute("edu", eduList); request.setAttribute("name", username); request.setAttribute("id", id); return "userselecteducate"; } public String insertcourse(){ String[] para=request.getParameterValues("edupara"); String userid=request.getParameter("userid"); if(para.length>0){ User us=userService.getUser(Long.parseLong(userid)); Set<Educate> edus=new HashSet<Educate>(); edus=us.getEducate(); for(String str: para ){ Educate educate=educateService.getForEdu(Long.parseLong(str)); /* Set users=new HashSet<User>(); users=educate.getUser(); System.out.println(users.size()); users.add(us); System.out.println(users.size()); educate.setUser(users); educateService.saveorUpdate(educate); */ edus.add(educate); } us.setEducate(edus); userService.saveOrUpdate(us); } return "insertcourse"; } public String deletecourse(){ String userid=request.getParameter("userid"); User us=userService.getUser(Long.parseLong(userid)); Educate edu=educateService.getForEdu(id); //edu.getUser().remove(us); Set<Educate> educates=new HashSet<Educate>(); educates=us.getEducate(); educates.remove(edu); us.setEducate(educates); userService.saveOrUpdate(us); try { inputStream = new ByteArrayInputStream("1".getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block try { inputStream = new ByteArrayInputStream("0".getBytes("UTF-8")); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); } return "ajax-success"; } @Override public void setServletRequest(HttpServletRequest arg0) { // TODO Auto-generated method stub this.request=arg0; } }
EducateAction類:
package com.ssh.action; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; import com.ssh.entities.Educate; import com.ssh.entities.User; import com.ssh.service.EducateService; import com.ssh.service.UserService; public class EducateAction extends ActionSupport implements ServletRequestAware{ /** * @author Administrator zhangshitong */ private static final long serialVersionUID = 1L; private Educate educate; private EducateService educateService; private HttpServletRequest request; private InputStream inputStream; private Long id; private UserService userService; public void setUserService(UserService userService) { this.userService = userService; } public void setId(Long id) { this.id = id; } public Long getId() { return id; } public InputStream getInputStream() { return inputStream; } public void setEducateService(EducateService educateService) { this.educateService = educateService; } public Educate getEducate() { return educate; } public void setEducate(Educate educate) { this.educate = educate; } public String addeducate(){ educate.setCreatetime(new Date()); System.out.println(educate); educateService.saveorUpdate(educate); return "addeducate"; } public String listeducate(){ List<Educate> list=educateService.getForList(); request.setAttribute("educate", list); return "listeducate"; } public String delete(){ System.out.println("this is id's value:"+id); //Set<User> users=new HashSet<User>(); //users=null; List<User> userList=userService.getForList(); Educate edu=educateService.getForEdu(id); Iterator<User> it=userList.iterator(); while(it.hasNext()){ User userListMember=it.next(); Set<Educate> setEducate=userListMember.getEducate(); if(setEducate.contains(edu)){ setEducate.remove(edu); } userService.saveOrUpdate(userListMember); } //edu.setUser(users); //educateService.saveorUpdate(edu); educateService.delete(id); //educateService.deleteCascade(edu); try { inputStream = new ByteArrayInputStream("1".getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block try { inputStream = new ByteArrayInputStream("0".getBytes("UTF-8")); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); } return "ajax-success"; } public String addcourse(){ List<Educate> list=educateService.getForList(); request.setAttribute("educate", list); request.setAttribute("userid", id); return "addcourse"; } @Override public void setServletRequest(HttpServletRequest arg0) { // TODO Auto-generated method stub this.request=arg0; } }
spring的application配置文件(事務管理):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 導入資源文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置 C3P0 數據源 --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <!-- 配置 SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> <property name="mappingLocations" value="classpath:com/ssh/entities/*.hbm.xml"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop> </props> </property> </bean> <!-- 配置 Spring 的聲明式事務 --> <!-- 1. 配置 hibernate 的事務管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 2. 配置事務屬性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 3. 配置事務切入點, 再把事務屬性和事務切入點關聯起來 --> <aop:config> <aop:pointcut expression="execution(* com.ssh.dao.*.*(..))" id="txPointcut"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config> </beans>
web.xml配置的過濾器:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>hibernateFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sessionFactory</param-value> </init-param> <init-param> <param-name>singleSession</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>