O2OA开发日志(报错总结)
提示:记录学习O2OA中遇到的大大小小的问题
文章目录
一、学习记录
1. 常规三步骤
- 了解需求,学习相关技术
- 代码实现,得到常规步骤
- 提取相同点和不同点,制作代码生成器
2. 框架结构分析
控制层
一个文件夹对应一张表
这个里面就是对数据库的增删改查
在idea中运行debug,进行远程调试
实体类Student
Student类的标准元模型类的名字是 Student_
3. 学习factory中的jap查询
- EntityManager
EntityManager是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储。 - CriteriaBuilder
CriteriaBuilder是一个工厂类,是一个工厂对象,安全查询的开始,用于构建JPA安全查询,用来创建安全查询的criteriaQuery对象。 - CriteriaQuery
CriteriaQuery 安全查询主语句,该对象是用来构建查询的。 - Root
Root 定义查询的From子句中能出现的类型 - Predicate
Predicate查询条件的拼接对应于where后面的添加表达式。 - 举例说明
4. 插入数据
-
save方法对数据库的插入操作比较直接,立刻生成insert语句将对象插入数据库,并返回主键值;
-
persist方法则会延迟插入数据,且没有返回值。persist在事务外部被调用时,不会触发insert语句。在事务内和save方法类似。
protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, JsonElement jsonElement ) throws Exception {
ActionResult<Wo> result = new ActionResult<>();
Wi wi = this.convertToWrapIn( jsonElement, Wi.class );
if( StringUtils.isEmpty( wi.getName() )) {
throw new ExceptionStudentEntityClassNameEmpty();
}
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
Student student = Wi.copier.copy( wi );
//启动事务
emc.beginTransaction( Student.class );
//校验并持久化对象
emc.persist(student, CheckPersistType.all );
//提交事务
emc.commit();
Wo wo = new Wo(student.getId());
result.setData(wo);
}
return result;
}
5. Wi与Wo
/**
* 用于接受前端传入的对象型参数的帮助类
*
*/
public static class Wi extends Student {
public static WrapCopier<Wi, Student> copier = WrapCopierFactory.wi( Wi.class, Student.class, null, JpaObject.FieldsUnmodify );
}
/**
* 用于输出响应内容的帮助类
*
*/
public static class Wo extends WoId {
public Wo( String id ) {
setId( id );
}
}
5. 实体类
简单说明一下注解的作用
varchar(50)(可以为空)
public static final String name_FIELDNAME = "name";
@FieldDescribe("文件名称.")
@Column(length = length_255B, name = ColumnNamePrefix + name_FIELDNAME)
@Index(name = TABLE + IndexNameMiddle + name_FIELDNAME)
@CheckPersist(allowEmpty = false)
private String name;
char(1)
// `kslb` char(1) DEFAULT NULL COMMENT '考生类别码',
public static final String kslb_FIELDNAME = "kslb";
@FieldDescribe("毕业类别码.")
@Column(length = length_2B, name = ColumnNamePrefix + kslb_FIELDNAME)
@Index(name = TABLE + IndexNameMiddle + kslb_FIELDNAME)
@CheckPersist(allowEmpty = true)
private String kslb;
datatime(可以为空)
public static final String actualCompletedTime_FIELDNAME = "actualCompletedTime";
@FieldDescribe("实际结束时间.")
@Temporal(TemporalType.TIME)
@Column(name = ColumnNamePrefix + actualCompletedTime_FIELDNAME)
@Index(name = TABLE + IndexNameMiddle + actualCompletedTime_FIELDNAME)
@CheckPersist(allowEmpty = true)
private Date actualCompletedTime;
boolean(可以为空)
public static final String manualCompleted_FIELDNAME = "manualCompleted";
@FieldDescribe("会议是否手工结束")
@Column(name = ColumnNamePrefix + manualCompleted_FIELDNAME)
@Index(name = TABLE + IndexNameMiddle + manualCompleted_FIELDNAME)
@CheckPersist(allowEmpty = true)
private Boolean manualCompleted;
Double(可以为空)
public static final String price_FIELDNAME = "price";
@FieldDescribe("价格.")
@Column(name = ColumnNamePrefix + price_FIELDNAME)
@CheckPersist(allowEmpty = true)
private Double price;
Integer
public static final String commentCount_FIELDNAME = "commentCount";
@FieldDescribe("评论数")
@Column(name = ColumnNamePrefix + commentCount_FIELDNAME)
@Index(name = TABLE + IndexNameMiddle + commentCount_FIELDNAME)
private Integer commentCount;
ID
public static final String application_FIELDNAME = "application";
@FieldDescribe("归属应用ID.")
@Column(length = JpaObject.length_id, name = ColumnNamePrefix + application_FIELDNAME)
@Index(name = TABLE + IndexNameMiddle + application_FIELDNAME)
@CheckPersist(allowEmpty = false)
private String application;
6. 多模块怎么实现的?
我的第一个猜想应该是这里进行部署
好家伙,结果是这样的
基于这个报错信息,我又有了新的猜测
果然是这个我的路径忘了修改才导致两个Action的路径冲突了!!!它终于出现了!!!!
7. 新增一个完整的实体(增删改查)
我采用一个预报到信息表(yx_new_student),进行演示说明
com.x.yxapp.core.entity包
- 编写entity类:YxNewStudent
自动生成serialVersionUID
编写每个字段(听说text类型有注解来表示?)
生成每个字段的 getter() 和 setter() - 在PersistenceProperties中添加类:YxNewStudent
public static class YxNewStudent {
public static final String table = "YX_NEW_STUDENT";
}
- com.x.yxapp.core.entity包中的操作就是这些,至于 YxNewStudent_ 文件是编译之后生成的,无须我们手动添加
com.x.yxapp.assemble.control
-
在com.x.yxapp.assemble.control 包中的 jaxrs包 中新建一个文件夹yxnewstudent ,然后将同级工程模板中的代码 copy 到 新文件夹yxnewstudent
-
修改 yxnewstudent 包中的异常类,并且自动生成serialVersionUID
-
在YxNewStudentAction中需要修改 path 路径,否则就会造成路径冲突从而产生bug
-
打开Action类 ,按下 ctrl + r 打开替换窗口 把 文件 的实体类都替换为YxNewStudent
替换之后会有一个 小错误,只需要新增一个YxNewStudentFactory类。
-
新增一个YxNewStudentFactory类,打开一个其他的Factory类,copy里面的内容到YxNewStudentFactory中再进行替换就行,完成后发现business这里调用方法有错误,
这里就需要在Business类中添加如下代码
上一个报错解决了,发现这里也缺少了类这个就是我们上一个讲的会自动生成的YxNewStudent_
现在我们把项目编译一下 mvn install
稍待片刻之后,显示BUILD SUCCESS 就表示成功啦!!!
打开 com.x.yxapp.core.entity 里面就会有刚刚编译生成的 YxNewStudent_ ,上面的报错也得到了解决
-
在x_yxapp_assemble_control类的 containerEntities字符串数组 中 添加 对实体类的引用
-
在ActionApplication类中新增代码,为了向外提供服务
-
最后再 执行 mvn install,生成 jar 和 war 会在store中,部署到服务器就OK啦!!!
8. 为一个实体添加功能接口
二、报错:加入新的jar和war后,无法启动服务器
问题描述:
加入新的jar和war后,无法启动服务器
重启服务器报错
就把工程模板一模一样的整上去,都可以部署成功
重启还是报空指针异常
原因分析:
终于解决了(但是我觉得这不是根本的原因,因为我也有部署成功后,重启还是报错的情况,这里让我想起一个细节:之前我都是用stop命令停止服务,后面我就采用exit命令了,不知道是不是因为这个呢。)
解决方案:
部署一直报错原来是因为顺序问题,但是空指针错误是因为什么呢?
三、报错:调用get方法,出现空指针异常
问题描述:
原因分析:
工程模板中有部分代码功能未使用,导致报空指针异常
解决方案:
注释掉不需要的内容
四、报错:不影响程序在服务器的运行
问题描述:
怎么说呢,这个是我在查看代码逻辑的时候发现的,
毛病就是这样一步一步引出来的
原因分析:
我目测是因为构造函数的参数不符合条件导致的问题,至于为什么运行没有报错,就不得而知了。
解决方案:
暂时没有解决
五、报错:
问题描述:
pow文件中的project一直报错
原因分析:
‘parent.relativePath’ of POM o2oa:o2oa_custom:6.2 (D:\SpringBoo\xgapp\yxapp\pom.xml) points at o2oa:o2oa_custom instead of o2oa:o2server, please verify your project structure
原来是因为外面还有一层pow文件,导致了指向存在问题,
解决方案:
这里我直接删掉了最外层的pow文件
六、报错:
问题描述:
原因分析:
缺少文件
解决方案:
修改这个文件的名字,与模块保持一致
七、报错:
问题描述:
原因分析:
根据报错信息的指引,我去自动生成了serialVersionUID
结果是问题还是没有解决,我发现应该是另外一个serialVersionUID还没有更改,再试一试!
好家伙还是错的
会不会是冲突了,好吧,不是这个问题,然后又有了新的尝试
依然没有解决问题,进行修改,应该是还有没修改完整的地方
算是解决了一半吧,应该是缺少另一个entity
其实之前就报过这个错,但是我的关注点错误了,导致一直没有找到根本的原因
现在我把另一个entity添加到containerEntities中,看看是否能解决问题?
终于成功解决了这个问题!!!!问题就是出在x_yxapp_assemble_control这个类中
抓住一个小细节,ksh这个字段为啥不在了?好家伙,继续寻找问题
经过对比后发现,ActionGet这个接口中是存在ksh的,但是ActionListAll缺消失了,经过代码对比分析后我更改了如下代码:
ksh出现了!!!原来这个代码可以隐藏字段!
public static List<String> Excludes = ListTools.toList(JpaObject.FieldsInvisible, YxAdmissionInfo.ksh_FIELDNAME);
解决方案:
将x_yxapp_assemble_control类中的内容补充完整。