一、数据库设计
需注意:
1. 考虑实体与实体之间的关系,如继承(学生和老师继承用户的属性,但他们分别是各自的)
2. 考虑变量的类型与大小(如Id的类型设置为varchar(23),其中前三位是类型(stu),中间17位为时间戳,后面的3位1到999的随机数)、上传时间的类型设置为char(17)
3. 数据库的字段最好用全部用大写,否则使用时要用双引号包含,数据库的值如果包含字母和数字时,用单引号括起来,否则会引发invalid denefite
二、后台设计
1.Springboot配置
# 驱动配置信息
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url = jdbc:oracle:thin:@172.20.94.204:1521:icreative
spring.datasource.username = itm
spring.datasource.password = itm
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
#连接池的配置信息
## 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
## 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
2.pom文件的配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jxufe</groupId>
<artifactId>online</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<name>online</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- spring-boot依赖项 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 数据连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
3.mybatis自动生成entity,mapper(generatorConfig.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<classPathEntry location="D:\java\maven\repository\com\oracle\ojdbc6\11.2.0.4\ojdbc6-11.2.0.4.jar" />
<context id="context1" defaultModelType="flat"
targetRuntime="MyBatis3">
<!-- 自动识别数据库关键字,默认false,如果设置为true,根据SqlReservedWords中定义的关键字列表; 一般保留默认值,遇到数据库关键字(Java关键字),使用columnOverride覆盖 -->
<property name="autoDelimitKeywords" value="false" />
<!-- 生成的Java文件的编码 -->
<property name="javaFileEncoding" value="UTF-8" />
<!-- 格式化java代码 -->
<property name="javaFormatter"
value="org.mybatis.generator.api.dom.DefaultJavaFormatter" />
<!-- 格式化XML代码 -->
<property name="xmlFormatter"
value="org.mybatis.generator.api.dom.DefaultXmlFormatter" />
<!-- beginningDelimiter和endingDelimiter:指明数据库的用于标记数据库对象名的符号,比如ORACLE就是双引号,MYSQL默认是`反引号 -->
<property name="beginningDelimiter" value="`" />
<property name="endingDelimiter" value="`" />
<!-- jdbc连接 -->
<jdbcConnection connectionURL="jdbc:oracle:thin:@172.20.94.204:1521:icreative"
driverClass="oracle.jdbc.driver.OracleDriver" password="itm" userId="itm" />
<!-- 类型转换 -->
<javaTypeResolver
type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl">
<!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) -->
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生成实体类地址 -->
<javaModelGenerator targetPackage="online.entity"
targetProject="online">
<property name="enableSubPackages" value="true" />
<!-- 是否针对string类型的字段在set的时候进行trim调用 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 生成接口dao和SqlProvider类 -->
<javaClientGenerator targetPackage="online.db"
targetProject="online" type="ANNOTATEDMAPPER">
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口
-->
<!-- 是否在当前路径下新加一层schema,eg:fase路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 配置表信息 -->
<table tableName="ED_COURSEITEM" domainObjectName="CourseSetTime"
enableCountByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" enableUpdateByExample="false">
<!-- schema即为数据库名 tableName为对应的数据库表 domainObjectName是要生成的实体类 enable*ByExample
是否生成 example类 -->
<!-- 忽略列,不生成bean 字段 -->
<!-- 指定列的java数据类型 -->
<columnOverride column="COURSERECID" property="courseRecordId"/>
<columnOverride column="COU_COURSERECID" property="c_courseRecord"/>
<columnOverride column="CID" property="courseId"/>
<columnOverride column="CLASSID" property="classId"/>
<columnOverride column="PLANSTARATTIM" property="planStartTime"/>
<columnOverride column="PLANENTINE" property="planendTime"/>
<columnOverride column="CLASSTATUS" property="classStatus"/>
<columnOverride column="AGOID" property="preClasssRecord"/>
</table>
</context>
</generatorConfiguration>
4.对各个层的框架,开始编写代码
(1) 分析各实体所需的功能,如果mybatis自动生成的方法不能满足,则需要新建Object类,将新的属性写在里面,新建ObjectMapper类,继承他的实体类,此后使用都用object类来调用方法,将新的方法添加在里面,注意新加的实体与其他实体的联系,一对多,一对一,然后在服务层进行实现,最后将映射在controller层。
(2) 注意在编写每一发方法的时候都要注意方法名的编写,要让别人看到你的方法就知道你要做什么,命名的规范很重要
1.object类
public class ClassObject extends online.entity.Class{
private String courseName;
private String teacherName;
private List<StudentObject> students;
private Integer startTime;
private List<DataObject> fileName;
private List<CommentObject> contextList;
//此处后期发现:这里最好设置为一个实体,并用Lis列出所有的实体项,这样用到什么直接调用就好
一般为 private List<TeacherObject> teacher;
注意取名的规范
生成get\set方法
2.ObjectMapper类
public interface ClassObjectMapper extends ClassMapper {
/**
*huhu
* @param classid
* 通过classid查询班级名称,教师姓名、学生姓名、上课时间,文件名,班级内部的评论内容
* @return
*/
@Select({ "select * from ED_CLASS", "where CLASSID = #{classId,jdbcType=VARCHAR}" })
@Results({ @Result(column = "CID", property = "courseId", jdbcType = JdbcType.CHAR, id = true),
@Result(column = "CLASSID", property = "classId", jdbcType = JdbcType.CHAR, id = true),
@Result(column = "USEID", property = "useid", jdbcType = JdbcType.CHAR),
@Result(column = "CLASSNAME", property = "className", jdbcType = JdbcType.VARCHAR),
@Result(column = "CLASSPEOPLE", property = "classPeople", jdbcType = JdbcType.DECIMAL),
@Result(column = "ENDENTERTIM", property = "endEnterTime", jdbcType = JdbcType.CHAR),
@Result(column = "CLASSCRETIM", property = "classCrateTime", jdbcType = JdbcType.CHAR),
@Result(column = "CLASSCRENAM", property = "classCrateName", jdbcType = JdbcType.VARCHAR),
@Result(column = "CLASSID",property="students",javaType=List.class,
many=@Many(select="online.objmapper.StudentObjectMapper.selectStudentsByClassID")),
@Result(column = "courseId", property = "CourseName", javaType=CourseObject.class,
one=@One(select="online.objmapper.CourseObjectMapper.selectCourseNameByID")),
@Result(column = "userid",property="teacherName",javaType=TeacherObject.class,
many=@Many(select="online.objmapper.TeacherObjectMapper.selectTeacherNameById")),
@Result(column = "couseId",property="startTime",javaType=ClassTimeObject.class,
one=@One(select="online.objmapper.ClassTimeObjectMapper.selectStartTimeById")),
@Result(column="CLASSID",property="fileName",javaType=List.class,
one=@One(select="online.objmapper.DataObjectMapper.selectFileNameById")),
@Result(column = "CLASSID",property="contextList",javaType=List.class,
one=@One(select="online.objmapper.CommentObjectMapper.selectCommentContextById"))
})
ClassObject selectList(String classid);
注意:1. 多个关系可以放在一起,
2. javaType:一个java类的完全限定名,或一个类型别名(通过typeAlias配置或者默认的类型,
如果映射到hashMap则需要明确指定javaType,如果映射到一个bean,MyBatis通常会自动判断属性类型
jdbcType仅仅需要对插入、更新、删除操作可能为空的列进行处理
3.select里面是对应Mapper的方法名路径,即以下方法。均要添加到服务层,但是以下不用添加到controller层
/**
*huhu
* @param classId
* 根据classid查看课程名
*/
@Select({ "select CNAME from ED_COURSE",
"where CID in (select CID from ED_CLASS where CLASSID= #{classId,jdbcType=VARCHAR})" })
@Results({ @Result(column = "CNAME", property = "courseName", jdbcType = JdbcType.VARCHAR)})
String selectCourseNameByID(String classId);
//此方法目前用不到了,因为可以直接用班级里的课程id,调用自动生成的方法即可,并且无论是查什么,select语句和results的内容都要写完整。下面是修改后的代码,selectProvider是多属性查询
@SelectProvider(type=ClassObjectSql.class,method="selectByClass")
@Results({ @Result(column = "CID", property = "courseId", jdbcType = JdbcType.CHAR, id = true),
@Result(column = "CLASSID", property = "classId", jdbcType = JdbcType.CHAR, id = true),
@Result(column = "USEID", property = "useid", jdbcType = JdbcType.CHAR),
@Result(column = "CLASSNAME", property = "className", jdbcType = JdbcType.VARCHAR),
@Result(column = "CLASSPEOPLE", property = "classPeople", jdbcType = JdbcType.DECIMAL),
@Result(column = "ENDENTERTIM", property = "endEnterTime", jdbcType = JdbcType.CHAR),
@Result(column = "CLASSCRETIM", property = "classCrateTime", jdbcType = JdbcType.CHAR),
@Result(column = "CID", property = "course", javaType=ClassObject.class,
one=@One(select="online.db.CourseMapper.selectByPrimaryKey")),
@Result(column = "USEID",property="teacher",javaType=ClassObject.class,
one=@One(select="online.db.TeacherMapper.selectByPrimaryKey")),
})
List<ClassObject> selClassCourseTeacherClassTimeByCourseIdUserIdClassId(ClassObject record);
3.服务层
服务层用来定义方法名和返回类型,也可以将mapper的方法合并在一起。
注意:只有controller层需要实现的方法,才用在service里面写
public interface DictService {
SysDict findById(Long id);
List<SysDict> findBySysDicts(SysDict sysDict,Integer offset,Integer limit);
boolean saveOrUpdate(SysDict sysDict);//对应Mapper中的insert和updateById方法,
boolean deleteById(Long id);//删除成功,则是boolean值
}
public interface ClassService {
//需备注:备注方法,点击方法名,shift+alt+J
int deleteByPrimaryKey(@Param("courseId") String courseId, @Param("classId") String classId);
int insert(Class record);
int updateByPrimaryKey(Class record);
ClassObject selectList(String classid);
ClassObject selTecClById(String classId);
}
4服务实现层
@Service
public class ClassServiceImpl implements ClassService {
@Autowired
private ClassObjectMapper classObjectMapper;
@Override
public int deleteByPrimaryKey(String courseId, String classId) {
return classObjectMapper.deleteByPrimaryKey(courseId, classId);
}
@Override
public int insert(Class record) {
record.setClassId(IdUtil.getNumber(IdType.Class));
//将自动获取id,和时间的代码都放在这里
return classObjectMapper.insert(record);
}
@Override
public ClassObject selectList(String classid) {
return classObjectMapper.selectList(classid);
}
@Override
public int updateByPrimaryKey(Class record) {
return classObjectMapper.updateByPrimaryKey(record);
}
@Override
public ClassObject selTecClById(String classId) {
return classObjectMapper.selTecClById(classId);
}
4.公共类(自动获取id)
Type
public enum IdType {
User,
Student,
Teacher,
Reply,
//若用可以自行添加
}
IdUtil
public class IdUtil {
public static String getNumber (IdType idType) {
int len=3;
String prefix="";
switch (idType) {
case User:
prefix="USE";
break;
case Student:
prefix="STU";
break;
case Teacher:
prefix="TEH";
break;
case Class:
prefix="ClA";
break;
case Comment:
prefix="COM";
break;
case Course:
prefix="COU";
break;
case Reply:
prefix="REP";
break;
default:
break;
}
return prefix+String.valueOf(System.currentTimeMillis())+getRandom(len);
}
private static String getRandom(int len) {
Random random=new Random();
double last = (1 + random.nextDouble()) * Math.pow(10, len);
String lastString = String.valueOf(last);
return lastString.substring(1, len + 1);
}
}
@Override是伪代码,所以是可写可不写的.它表示方法重写,写上会给我们带来好处.
1.可以当注释用,方便阅读.
2.告诉阅读你代码的人,这是方法的复写.
3.编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.
5.controller层
@Controller
@RequestMapping("/class")
public class ClassController {
@Autowired
private ClassService classService;
/**
*huhu
* @param request
* @param response
* deleteByPrimaryKey
* 删除班级信息
* @return
*/
@ResponseBody
@RequestMapping("/delete")
private String deleteByPrimaryKey(HttpServletRequest request,HttpServletResponse response) {
classService.deleteByPrimaryKey(request.getParameter("courseId").trim() ,request.getParameter("classId").trim());
return "删除成功";
//删除要考虑级联删除的问题,为了安全性的考虑,不能如下写,应该直接在前台判断,如果其他表有这个内容,则不能删除
if((courseService.deleteClassByCourseId(Parse(request).getCourseId())) != 0) {
courseService.deleteByPrimaryKey(Parse(request).getCourseId());
}else {
courseService.deleteByPrimaryKey(Parse(request).getCourseId());
}
return "删除成功";
}
修改后的代码
/**
*huhu
* @param request
* @param response
* updateByPrimaryKeySelective
* 更新班级信息
* @return
*/
@ResponseBody
@RequestMapping("/update") public String update(HttpServletRequest request,HttpServletResponse response) {
System.out.println("huhu");//用来验证是否进入该方法
System.out.println(Parse(request).getClassName())//判断className旳值
ClassObject classes=Parse(request);
int reval= classService.updateByPrimaryKeySelective(classes);
if(reval != 0) {//此处返回值,方便前台判断
return "1";
}
return "0";
}
/**
*huhu
* @param request
* @param response
* insert
* 增加班级信息
* @return
*/
@ResponseBody
@RequestMapping("/insert")
public int insert(HttpServletRequest request,HttpServletResponse response) {
ClassObject classes=Parse(request);
return classService.insert(classes);
}
/**
*huhu
* @param request
* @param response
* selectList
* 根据id查询班级名称,教师姓名、学生姓名、上课时间,文件名
* @return
*/
@ResponseBody
@RequestMapping("/selectList")
public ClassObject selectList(HttpServletRequest request,HttpServletResponse response) {
/*classes.setCourseName(request.getParameter("courseName"));
classes.setTeacherName(request.getParameter("teacherName"));
classes.setStudents(new ArrayList<StudentObject>());
classes.setStartTime(new Integer(request.getParameter("startTime")));
classes.setFileName(new ArrayList<DataObject>());*/
return classService.selectList(request.getParameter("classId").trim());
}
private ClassObject Parse(HttpServletRequest request) {
ClassObject classes=new ClassObject();
if(request.getParameter("classId")!=null) {
classes.setClassId(request.getParameter("classId").trim());
}
if(request.getParameter("courseId")!=null) {
classes.setCourseId(request.getParameter("courseId").trim());
}
if(request.getParameter("useid")!=null) {
classes.setUseid(request.getParameter("useID").trim());
}
if(request.getParameter("className")!=null) {
classes.setClassName(request.getParameter("className").trim());
}
if(request.getParameter("classPeople")!=null) {
classes.setClassPeople(new BigDecimal(request.getParameter("classPeople").trim()));
}
if(request.getParameter("endEnterTime")!=null) {
classes.setEndEnterTime(request.getParameter("endEnterTime").trim());
}
if(request.getParameter("classCreateTime")!=null) {
classes.setClassCrateTime(request.getParameter("classCreateTime").trim());
}
if(request.getParameter("classCreateName")!=null) {
classes.setClassCrateName(request.getParameter("classCreateName").trim());
}
return classes;
}
}
注意:1. insert和update方法都要是用公共类,为了避免冗余,将其写为单独的类(Parse)进行调用
2. requestMapping 对应的是相应的映射文件,在网页中跳转的页面
3.访问页面地址:http://localhost:8080/data/update?useid=4&dataId=201801&dataName=a&datasize=2&dataType=txt&dataUrl=/aa
动态SQL Provider,可以完成多条件查询
package online.sqlProviderobjiect;
import org.apache.ibatis.jdbc.SQL;
import org.apache.ibatis.session.SqlSession;
import com.sun.tools.corba.se.idl.constExpr.And;
import online.db.ClassSqlProvider;
import online.object.ClassObject;
public class ClassObjectSql extends ClassSqlProvider {
public String selectByClass(ClassObject record) {
SQL sql=new SQL();
sql.SELECT("CID, CLASSID, USEID, CLASSNAME, CLASSPEOPLE, ENDENTERTIM, CLASSCRETIM");
sql.FROM("ED_CLASS");
if(record.getClassName() != null) {
sql.WHERE("CLASSNAME=#{className,jdbcType=VARCHAR}");
}
if(record.getClassId() != null) {
sql.WHERE("CLASSID=#{classId,jdbcType=CHAR}");
}
return sql.toString();
}
}
在classMapper加,注此处已在修改的代码显示,需稍加修改
@SelectProvider(type=ClassObjectSql.class,method="selectByClass")
List<ClassObject> selectByClass(ClassObject record);
前台若用jsp交互,则需添加依赖servlet、jsp、jstl,注如果是web项目,可以将maven仓库中的jstl的jar包拷到lib文件下。
<!--web-->
<!--支持 Servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--支持 JSP-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<!--支持 JSTL-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
前台代码的设计
分析:
1. 开始使用的是bootstrap,但是在后期的操作中对更新操作没有完成,不知道如何将将获取的值传入使得更更新成功,由于时间原因,改为easyui框架,现复制bootstrap框架。
2. 点击左边,右边相应的页面跳动用的是framset,但相对来说非常不灵活,速度也慢。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>学生信息管理</title>
<link rel="stylesheet" href="../css/bootstrap.css">
<link rel="stylesheet" href="../css/bootstrap-table.css">
<link rel="stylesheet" href="../css/bootstrap-editable.css">
<link rel="stylesheet" href="../css/bootstrap.min.css">
<link rel="stylesheet" href="../css/bootstrap-theme.min.css">
<link href="../css/style.css" rel="stylesheet">
<script src=" ${pageContext.request.contextPath} /js/stuview.js"></script>
</head>
<style>
.table {
margin-left: 20px;
}
.easyui-pagination{
margin-left: 800px;
}
</style>
<body>
<table id="table" ></table>
<script src="../js/jquery-3.0.0.min.js"></script>
<script src="../js/bootstrap-table.js"></script>
<script src="../locale/bootstrap-table-zh-CN.js"></script>
<script src="../js/bootstrap-editable.js"></script>
<script >
$(function () {
//1.初始化Table
var oTable = new TableInit();
oTable.Init();
});
var TableInit = function () {
var oTableInit = new Object();
//初始化Table
oTableInit.Init = function () {
$('#table').bootstrapTable({
url: '/teacher/selectAll', //请求后台的URL(*)
method: 'post', //请求方式(*)
pagination: true, //是否显示分页(*)
pageNumber: 1, //初始化加载第一页,默认第一页
pageSize: 10, //每页的记录行数(*)
pageList: [10, 25, 50, 100], //可供选择的每页的行数(*)
search: true, //是否显示表格搜索,
showRefresh: true, //是否显示刷新按钮
editable:true,
onEditableSave: function (field, row, oldValue, $el) {
$.ajax({
type: "post",
url: "/teacher/addAll",
data: {strJson:JSON.stringify(row)},
dataType: 'JSON',
success: function (data, status) {
if (status == "success") {
alert('提交数据成功');
}
},
error: function () {
alert('编辑失败');
},
complete: function () {
}
});
},
columns: [
{
field:'teaUserId',
title: '教师用户Id',
align: 'center', // 左右居中
valign: 'middle', // 上下居中
editable:false
},{
field:'teaUserName',
title: '教师用户名',
align: 'center', // 左右居中
valign: 'middle', // 上下居中
editable:{
type:'text',
validate:function(value){
if($.trim(value)==''){
return '用户名不能为空';
}
}
}
//editable:true
},],
onLoadSuccess: function(data){ //加载成功时执行
alert("加载成功"+data);
},
onLoadError: function(){ //加载失败时执行
layer.msg("加载数据失败", {time : 1500, icon : 2});
},
onEditableHidden: function(field, row, $el, reason) { // 当编辑状态被隐藏时触发
if(reason === 'save') {
var $td = $el.closest('tr').children();
$td.eq(-1).html((row.price*row.number).toFixed(2));
$el.closest('tr').next().find('.editable').editable('show'); //编辑状态向下一行移动
} else if(reason === 'nochange') {
$el.closest('tr').next().find('.editable').editable('show');
}
},
//保存
/* onEditableSave: function (field, row, oldValue, $el) {
//可进行异步操作
$.ajax({
type: "post",
url: "/teacher/addAll",
data: row,
dataType: 'JSON',
success: function (data, status) {
if (status == "success") {
alert('提交数据成功');
}
},
error: function () {
alert('编辑失败');
},
complete: function () {
}
});
}, */
//行样式
rowStyle: function (row, index) {
var classesArr = ['success', 'info'];
var strclass = "";
if (index % 2 === 0) {//偶数行
strclass = classesArr[0];
} else {//奇数行
strclass = classesArr[1];
}
return { classes: strclass };
},//隔行变色
});
window.actionEvents={
'click .delete':function(e,value,row,index){
alert(JSON.stringify(row));
alert(row.teaUserName)
$.ajax({
url:"/teacher/delete",
type:"POST",
data: row,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async:false,
dataType: "json",
success: function (data) {
if(data=="1"){
alert("成功");
}
}
});
},'click .save':function(e,value,row,index){
alert(JSON.stringify(row));
//var datasource=JSON.stringify(row);
//alert(JSON.stringify(row).length)
alert(row)
$.ajax({
url:"/teacher/addAll",
type:"POST",
data: row,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async:false,
dataType: "json",
success: function (data) {
if(data=="1"){
alert("成功");
}
}
});
},
'click .edit':function(e,value,row,index){
alert(JSON.stringify(row));
$('#table').editableTableWidget();
/* $('#table').editable({
type:'text'
})
alert('You click like action, row: ' + JSON.stringify(row));
*/
},
}
};
//得到查询的参数
oTableInit.queryParams = function (params) {
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit, //页面大小
offset: params.offset, //页码
departmentname: $("#txt_search_departmentname").val(),
statu: $("#txt_search_statu").val()
};
return temp;
};
return oTableInit;
};
</script>
</body>
easui框架设计前台界面:
1. 优点: 使用官网的代码能实现相应的效果,有js代码可以参考
2.自己遇到的问题:
(1) 关联表的数据的更新和删除问题。从数据库的原理来说,判断一个表能否删除,要看它所含的其他表的元素,是否还在那个表,如果在就不能删除。不在就可以进行的删除。
更新操作也是同理,目前更新操作使用下拉列表的方式,避免更新到其他表没有的元素。
(2) 对于各个表之间的逻辑,分配好任务,不然之前做的都会白做,或功能重复,
$(function() {//此处是更新操作,现将对应的数据取出来,然后放在下拉框中
$.ajax({
method:'POST',
url:'/teacher/selectAll',//注意url的两个斜杠
async:false,//是否缓存
dataType:'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success:function(data){
var teacher=data;
$('#tt').datagrid({
title: '课程信息',
// iconCls: 'icon-edit',
width:1300,
height: 500,
singleSelect: true,//只能单选一行
idField: 'courseId',
url: '/course/selectiveCourseInfo',
columns: [
[{
field:'courseId',
title:'课程ID',
align: 'center',
width:160
},{
field:'courseName',
title:'课程名称',
align: 'center',
width:100,
editor:'text',
formatter:function(value,row,index){
if(row.course){
var courseName=row.course.courseName;
return courseName;
/*多表进行映射,row表示当前行,注意如果是一对多的关系,就要用数组遍历
formatter:function(value,row,index){
if(row.students){
for(var i=0;i<row.students.length;i++){
var stuUserName=row.students[i].stuUserName;
}
return stuUserName;
}else {
return value;
}
for(var i=0;i<row.classTime.length;i++){
var startTime=row.classTime[i].startTime;
} }else{
return value;
}
},
},
*/ {
field:'useid',
title:'教師姓名',
align:'center',
width:100,
editor:{
type:'combobox',//下拉列表
options:{
valueField:'teaUserId',
textField:'teaUserName',
data:teacher,
required:true
}
},
formatter:function(value,row,index){
for(var i=0;i<teacher.length;i++){
if(teacher[i].teaUserId==value)
return teacher[i].teaUserName;
}
return value;
},
},{
field: 'status',
title: 'Status',
width: 50,
align: 'center',
editor: {
type: 'checkbox',
options: {
on: 'P',
off: ''
}
}
}, {
field: 'action',
title: 'Action',
width: 80,
align: 'center',
formatter: function(value, row, index) {
if (row.editing) {
var s = '<a href="#" οnclick="saverow(this)">Save</a> ';
var c = '<a href="#" οnclick="cancelrow(this)">Cancel</a>';
return s + c;
} else {
var e = '<a href="#" οnclick="editrow(this)">Edit</a> ';
var d = '<a href="#" οnclick="deleterow(this)">Delete</a>';
return e + d;
}
}
}
]],
onBeforeEdit: function(index, row) {
row.editing = true;
updateActions(index);
},
onAfterEdit: function(index, row) {
row.editing = false;
updateActions(index);
},
onCancelEdit: function(index, row) {
row.editing = false;
updateActions(index);
}
});
}
});
});
function updateActions(index) {
$('#tt').datagrid('updateRow', {
index: index,
row: {}
});
}
function getRowIndex(target) {
var tr = $(target).closest('tr.datagrid-row');
return parseInt(tr.attr('datagrid-row-index'));
}
function editrow(target) {
$('#tt').datagrid('beginEdit', getRowIndex(target));
}
//删除操作
function deleterow(target) {
$.messager.confirm('Confirm', 'Are you sure?', function(r) {
if (r) {
$('#tt').datagrid('deleteRow', getRowIndex(target));
var deleted = $("#tt").datagrid('getChanges',"deleted");//获取删除的行
var data = {};
data.Deleted = deleted;
for (var i = 0; i < deleted.length; i++) {
var courseId=deleted[i].courseId;
}
$.ajax({
url: '/course/delete',
type: 'POST',
data: {
'courseId':courseId,
},
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async:false,
dataType: "json",
success: function (data) {
if(data=="1"){
alert("删除成功");
setTimeout(function(){
window.location.href = "/course/courseview";
});
}
}
});
}
});
}
//保存操作
function saverow(target) {
$('#tt').datagrid('endEdit', getRowIndex(target));
var len = $('#tt').datagrid('getChanges').length;
if (len > 0) {
var inserted = $("#tt").datagrid('getChanges',"inserted");//获取新添加的行
alert(JSON.stringify(inserted))
var updated = $("#tt").datagrid('getChanges',"updated");//获取修改的行
alert(JSON.stringify(updated));
var data = {};
data.Inserted = inserted;
data.Updated = updated;
//判断是否是更新操作
if(JSON.stringify(updated).length>2){
alert(JSON.stringify(updated).length)
alert("执行了更新")
for (var i = 0; i < updated.length; i++) {
var courseId=updated[i].courseId;
var useid=updated[i].useid;
alert(useid)
var courseName=updated[i].courseName;
var courseTime=updated[i].courseTime;
var courseCost=updated[i].courseCost;
}
$.ajax({
url: '/course/update',
type: 'POST',
data: {
'courseId':courseId,
'userId':useid,
'courseName':courseName,
'courseTime':courseTime,
'courseCost':courseCost,
},
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async:false,
dataType: "json",
success: function (data) {
if(data=="1"){
alert("成功");
setTimeout(function(){
window.location.href = "/course/courseview";
});
}
}
});
}
//判断是否是插入操作
if(JSON.stringify(inserted).length>2){
alert(JSON.stringify(inserted));
alert(inserted);
alert("执行了插入")
for (var i = 0; i < inserted.length; i++) {
var courseId=inserted[i].courseId;
var useid=inserted[i].useid;
alert(useid)
var courseName=inserted[i].courseName;
var courseTime=inserted[i].courseTime;
var courseCost=inserted[i].courseCost;
}
$.ajax({
url: '/course/add',
type: 'POST',
data: {
'courseId':courseId,
'userId':useid,
'courseName':courseName,//此处的数据跟json数据的格式一致,如果遇到错误,就在前台用alert,后台相应的方法内System,out打印
'courseTime':courseTime,
'courseCost':courseCost,
},
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async:false,
dataType: "json",
success: function (data) {
if(data=="1"){
alert("成功");
setTimeout(function(){//操作完成后跳转
window.location.href = "/course/courseview";
});
}
}
});
}
}
else {
alert("没有发生变化的数据!");
return;
}
}
function cancelrow(target) {
$('#tt').datagrid('cancelEdit', getRowIndex(target));
}
function insert() {
var row = $('#tt').datagrid('getSelected');
if (row) {
var index = $('#tt').datagrid('getRowIndex', row);
} else {
index = 0;
}
$('#tt').datagrid('insertRow', {
index: index,
row: {
status: 'P'
}
});
$('#tt').datagrid('selectRow', index);
$('#tt').datagrid('beginEdit', index);
}
</script>
</head>
<body>
<div style="margin: 10px 0">
<a href="#" class="easyui-linkbutton" οnclick="insert()">
添加课程</a>
</div>
<table id="tt"></table>
</body>
</html>
获取id,查看老师的信息,老师所在的班级、课程
var teaUserId="<%=session.getAttribute("teaUserId")%>";
//alert(teaUserId)
$('#tt').datagrid({
title: '老师信息',
// iconCls: 'icon-edit',
width:1300,
height: 500,
singleSelect: true,
idField: 'teaUserId',
url: '/teacher/selective?teaUserId='+teaUserId,
columns: [
[{
field:'teaUserId',
title: '教师用户Id',
align: 'center',
width:152
},
获取id的另一个方法:
url: '/payOrders/selClassStu?classId='+localStorage.getItem("classId"),
localStorage获取存储的key值