2018-10-15:级联操作与类型转换
级联操作
@OneToMany(mappedBy="teacher")
@Cascade(value={CascadeType.DELETE})
Query query = session.createQuery("update teacher set birthday = ?
,imgsrc = ? ,tdesc = ? where tno = ? ");
query.setDate(0,teacher.getBirthday());
query.setStirng(1,teacher.getImgsrc());
query.set ...
- 级联操作:persistent update delete none all
新增 修改 删除
- 级联新增 当新增主键(外键)对象的时候 如果关联了还未保存到数据
的外键(主键)对象,就一并保存例如 新增一个班级的时候,顺便把第一个
学生添加了新增加一名学生发现这个学生所在的班级还不存在,顺便把班级
也添加了
- 级联修改 当主键表修改了主键,外键表原来的对应的外键字段就不合法
了,需要一并修改
- 级联删除 当删除一条主键,同时把该主键对应的外键删除了
- 如果一个类的操作,不想级联操作产生
- 关系编写mappedBy 表示级联由对方操作,但是由于不能双方都写
mappedBy如果另外一方有修改不操作级联的时候,就只能直接编写sql语句
2.自己编写sql语句
- 不合理级联产生的原因
- 对象查询开启了延迟加载,所以在只修改自身基本的属性的时候,没有将
关联数据查询
查询teacher由于延迟加载 clazzs为空
- 修改这个对象所带的关联对象是空的,所以这个时候做级联将原来的关联
删除
保存teacher,clazzs为空 所以 级联操作认为这个教师没有班级,所
以将原来班级的外键全部修改为null
- hibernate的设定,修改自己本身属性 自己编sql语句,维护关联关系使用
update()或者merge方法
- 以修改学生信息为例
- 管理员审核学生有个页面 (修改状态字段) updateState(){编
写sql语句}
- 学生修改如联系电话等基本属性有个页面(修改电话 家庭住址等字段)
updateInfo{编写sql语句}
- 学生修改密码页面 (修改密码字段)updatePwd(){编写sql}
- 学生修改选课 (修改关系,通过新增和删除 修改sc选课表中的记录
) updateSelectCourse{调用update()或者merge方法}
- 在真正需要修改关联关系的时候,需要给对象配置好关联集合,需struts
输出和接受接受值的时候 将对象转换为 对象主键集合 ,将对象主键 转换
为对象,内容见struts相关内容。
类型转换
在基础的web处理中,如果页面提交的内容(默认全部为String),但需要
对应的填入 int Date 等类型,需要编写类型转换代码
struts内置了基础的类型转换器,所以基础类型不需要配置自动转换
struts 也可以自定义配置集合类型转换器
例如 教师 带 班,修改教师带班,页面上其实也只有String
Teacher clazzs(集合为 teacher成员变量)
手动类型转换
1.struts默认不支持 List Set 这类的集合自动转换 需要配置类型转换器(
暂时没有讲,需要深刻理解 范型 和 反射机制)
2.页面只能传递 字符串(基本数据类)或者基本类型数组自动注入到
- 标签的name和strust成员变量对应
<s:checkboxlist name="cnos" list="%{#request.clazzs}"
listKey="cno"
listValue="cname" value="#request.cnos">
- 改造成员变量的 get set方法(
- 因为关联对象 是集合,而struts页面标签能够和数组自动匹配,显示的
时候把集合变数组(get)
public String[] getCnos() {
List<Clazz> clazzs = teacher.getClazzs();
int size = clazzs.size();
cnos = new String[size];
for(int i = 0 ;i< size;i++){
cnos[i] = clazzs.get(i).getCno();
}
return cnos;
}
- hibernate又只认对象,保存修改的时候 需要把数组变集合)
//数组变集合,hibernate 只认对象集合
public void setCnos(String[] cnos) {
this.cnos = cnos;
clazzs = new ArrayList<Clazz>();
for(String cno:cnos){
Clazz clazz = new Clazz();
clazz.setCno(cno);
clazzs.add(clazz);
}
//struts自己的调用顺序
//teacher.setClazzs(clazzs);
}
- 将集合关联给 对象 操作数据库,级联修改(前提 自己控制级联关系要
写joinColumn,不能写mappedBy 是表示把关系给别人控制)
// 修改一个教师
public String updateTeacher() {
teacher.setClazzs(clazzs);//在这写保证赋完值才 执行
操作数据库
Serializable result =
teacherServiceI.updateTeacher(teacher);
return "updateSuccess";
}
- hibernate 先取对象,去掉原来的关联对象,关联新的对象集合后进行修
改
//取得原来的一,去掉原来一的关系,设置新的关系后 修改一
Teacher resultTeacher = getTeacherByTno(teacher.getTno());
//将页面传递过来的teacher对应的最新班级集合 赋值给关联的
teacher
resultTeacher.getClazzs().removeAll
(resultTeacher.getClazzs());
for(Clazz clazz:teacher.getClazzs()){
resultTeacher.getClazzs().add(clazz);
}
- 页面设置 注意form给主键
<s:form action="teacherAction_updateTeacher">
${teacher.tname}教师,您所带的班级有
${fn:length(teacher.clazzs)}//访问具体属性会发送sql语句
<s:property value="name"/>
<s:hidden name="teacher.tno" value="%{#request.teacher.tno}"/>
<s:checkboxlist name="cnos" list="%{#request.clazzs}"
listKey="cno"
listValue="cname" value="#request.cnos">
</s:checkboxlist>
<s:submit value="修改选课"/>
</s:form>
- 记得存放request
ServletActionContext.getRequest().setAttribute("cnos",getCnos());
关联数据库对象和页面对象:teacher = dbteacher;
页面获取集合的大小是为了让延迟加载去加载关联对象的查询,否则对象会
空指针。
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions"
prefix="fn"%>
${teacher.tname}教师,您所带的班级有
${fn:length(teacher.clazzs)}
- 类似的操作:学生修改选课 使用学生级联课程
快递员取消自己的任务
任务发布者取消自己的任务