hibernate中两表一对一关系 和 session.save()方法和 session.saveOrUpdate()方法
2017-02-11 10:43
417 查看
问题描述:在做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;
@Entity
public 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.java
package model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public 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.java
package 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操作。返回值是void
save():在数据库中生成一条记录,如果数据库中有,会报错说有重复的记录。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>
初学者入门,如有不合适的地方还请指出,共同进步
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;
@Entity
public 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.java
package model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public 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.java
package 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操作。返回值是void
save():在数据库中生成一条记录,如果数据库中有,会报错说有重复的记录。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>
初学者入门,如有不合适的地方还请指出,共同进步
相关文章推荐
- [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作
- Hibernate深入理解----03Session缓存核心方法(save()和persist(),get()和load(),update()和saveOrUpdate,delete()和evil()
- hibernate框架中session的save() 和 update() 方法的区别 saveOrUpdate()方法
- hibernate中save,update,saveOrUpdate与三大状态的关系
- hibernate的save和saveOrUpdate方法
- Hibernate中对象的三种状态以及Session类中saveOrUpdate方法与merge方法的区别
- Hibernate中save、saveorupdate、persist方法的区别
- Hibernate Session中的save(),update(),delete(),saveOrUpdate() 细粒度分析
- hibernate中各种保存方法的区别 save persist update saveOrUpdate merge lock
- hibernate--session的CRUD方法, delete, load,get,update,saveorupdate, clear, flush
- hibernate——Session接口中定义的saveOrUpdate()方法浅析
- 在hibernate中save() saveOrUpdate() update() meger方法的讲解
- Hibernate学习篇12——session方法之save与update
- hibernate的save和saveOrUpdate方法
- Java - Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?
- Hibernate的Session接口中save/delete/update方法2个参数(entityName)的深入解析
- Hibernate中对象的三种状态以及Session类中saveOrUpdate方法与merge方法的区别
- 使用saveOrUpdate方法时,若hibernate的session存在了两个具有相同id的不同实体,则会报错
- hibernate的Session的saveOrUpdate等方法的使用
- hibernate的save(),saveOrUpdate(),update(),merge()方法的使用