问题描述:在做hibernate和struts2整合的小项目(学生管理系统)中,将学生对应的紧急联系人在页面上输入信息后保存到数据库中。
contact.jsp页面显示
这里分析的学生和紧急联系人是一对一的关系,这两个表的主键都是id设置自动增长,联系人主键id作为学生表的外键cid。Student(id,cid,name,sex,phone,grade,photo) 从表Contact(id,name,sex,relation,phone) 主表
两个表对应着的javabean对象类:
可以看到在Javabean中这两个类中已经注解配置了一对一关系,并且在student中加入了cid外键字段。
在从表中加入Contact contact属性,并设置其setter和getter。在其setter和getter前设置注解,表示与Contact的一对一关系,并加入列cid,设置为唯一的。
@OneToOne @JoinColumn(unique=true,name="cid")在主表中写Student student属性,并写其setter和getter。在其setter和getter前添加注解配置,表示与Student表的一对一关系。这里不再主表中添加指向Student的外键,所以配置@OneToOne时,要添加属性mappedBy
@OneToOne(mappedBy="contact")Studnet.java
package model;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.OneToOne;@Entitypublic class Student { PRivate int id; private String name; private String pwd; private String phone; private String grade; private String photo; private String sex; private Contact contact; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getGrade() { return grade; } public void setGrade(String grade) { this.grade = grade; } public String getPhoto() { return photo; } public void setPhoto(String photo) { this.photo = photo; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @OneToOne @JoinColumn(unique=true,name="cid") public Contact getContact() { return contact; } public void setContact(Contact contact) { this.contact = contact; }}Contact.javapackage model;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.OneToOne;@Entitypublic class Contact { private int id; private String name; private String sex; private String relation; private String phone; private Student student; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getRelation() { return relation; } public void setRelation(String relation) { this.relation = relation; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @OneToOne(mappedBy="contact") public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } }在hibernate.cfg.xml文件中配置这两个Javabean:
hibernate.cfg.xml:
<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <property name="connection.driver_class">com.MySQL.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/curricula</property> <property name="connection.username">jack</property> <property name="connection.passWord">12345678</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">update</property> <mapping class="model.Student" /> <mapping class="model.Contact" /> </session-factory></hibernate-configuration>写DAO中更新联系人表方法和Action中的方法(在struts.xml中采用通配符方式配置,这里不细说)ContactDAO:这里用的就是saveOrUpdate方法
package common;import org.hibernate.Session;import org.hibernate.Transaction;import model.Contact;public class ContactDAO { //定义公共变量 Session session; //更新或者保存联系人的方法 public void updateContact(Contact contact) { session=HibernateUtil.openSession(); Transaction tx=session.beginTransaction(); session.saveOrUpdate(contact); tx.commit(); session.close(); }}ContactAction.javapackage Action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;import common.ContactDAO;import common.StudentDAO;import model.Contact;import model.Student;public class ContactAction extends ActionSupport { /** * */ private static final long serialVersionUID = 1L; private Contact contact; public Contact getContact() { return contact; } public void setContact(Contact contact) { this.contact = contact; } private StudentDAO sdao=new StudentDAO(); private ContactDAO cdao=new ContactDAO(); //保存或者更新联系人的方法 public String updatecontact() { //得到request对象 HttpServletRequest request=ServletActionContext.getRequest(); //得到sess对象 HttpSession session=request.getSession(); //从session中拿到学生 Student student= (Student) session.getAttribute("STUDENT"); //保存联系人到数据库 cdao.updateContact(contact); //建立Student和Contact的联系,谁设置外键,用谁其中的setter设置另一个对象 student.setContact(contact); //保存更新后的学生信息到数据库中 sdao.updateStudent(student); session.setAttribute("STUDENT",student); return "main"; }}发现的问题:当在contact.jsp页面上修改联系人信息的时候,再点击进入contact.jsp时,信息确实是在页面上显示更新了。但是 点击提交去看数据库中时,发现student表中的cid字段(外键)发生变化,同时contact表中是多了一条更新信息之后的记录(不是在第一次设置紧急联系人的时候的那条记录上进行更新)。再看控制台执行的也是 对contact表 进行 insert语句。
问题原因:这里调用的是saveOrUpdate方法,就要了解这个方法。
saveorupdate():如果传入的对象在数据库中有就做update操作,如果没有就做save操作。返回值是voidsave():在数据库中生成一条记录,如果数据库中有,会报错说有重复的记录。save方法返回的是插入数据的主键update():就是更新数据库中的记录
主键在saveorupdate()方法中是起着关键作用的,当主键为空时进行insert,当主键不为空时进行update。
而做的contact.jsp页面上没有传入后台Action id值,所以当调用saveOrUpdate方法时,拿不到id值,一直执行save方法。也就出现刚才的结果
解决办法:应该在contact.jsp页面上加一个隐藏变量<input type="hidden" name="contact.id" value="${sessionScope.STUDENT.contact.id}"/> 传入后台Action中,这样每次保存或更新contact时,就可以根据id值做出save还是update的选择,解决这个记录冗余的问题。
最后修改后的contact.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>紧急联系人页面</title><link rel="stylesheet" type="text/CSS" href="${pageContext.request.contextPath}/css/TableStyle.css"><script type="text/Javascript" src="${pageContext.request.contextPath}/jslib/jquery-3.1.1.js"></script><script type="text/javascript">$(function(){ if($("[name='contact.sex']:checked").length==0){ $("[name='contact.sex']").eq(0).attr("checked",true); }})</script></head><body><h3>紧急联系人页面</h3><br><br><s:if test="#session.STUDENT==null"> <jsp:forward page="login.jsp"></jsp:forward></s:if><s:else><form action="${pageContext.request.contextPath}/contact/updatecontact" method="post"><table class="bordered"><tr><td>姓名:</td><td><input type="hidden" name="contact.id" value="${sessionScope.STUDENT.contact.id}"/><input type="text" name="contact.name" value="${sessionScope.STUDENT.contact.name}"></td></tr><tr><td>关系:</td><td><input type="text" name="contact.relation"value="${sessionScope.STUDENT.contact.relation}"></td></tr><tr><td>性别:</td><td><s:radio list="#{'男':'男','女':'女'}" theme="simple" name="contact.sex" value="#session.STUDENT.contact.sex"/></td></tr><tr><td>电话:</td><td><input type="text" name="contact.phone" value="${sessionScope.STUDENT.contact.phone}"></td></tr><tr><td colspan="2"><input type="submit" value="提交"></td></tr></table></form></s:else><br><br><a href="${pageContext.request.contextPath}/main.jsp">返回主页面</a></body></html>初学者入门,如有不合适的地方还请指出,共同进步
新闻热点
疑难解答