SpringBoot+JPA+Swagger(4)
这几天主要是熟悉公司的项目生成工具,遇到并解决了其中几个bug
问题一: JPA建表失败,所有实体类均无法自动建表
- 因为实体类属性在数据库表中的属性赋值时,未小写,导致JPA建表时无法识别
例如:
varchar
类型,却赋了一个VARCHAR
,数据库无法识别,就没有建表,之后的插入外键时,检测数据库不存在就会报错
因此在控制台报的只有插入外键时错误,causeby 数据库表 dont exit
问题二:插入数据时,UUID与实际解析的XML对应UUID不匹配
- 项目生成工具建立的模型,所有的实体类都是继承于
BaseEntity
,该类中定义了主键UUID以及其产生策略,@Generator
- 在使用JPA库的
save()
函数时,尽管传进去时entity的UUID为XML中的UUID,但是在save()的过程中,依旧被替换为基类的构造方式 - 具体实现通过看源码没有找到,在
<?extends>save()
处无法向下查询 - 解决办法,新建一个DAO接口,使用
@Modify
@Query
执行自己自定义的sql语句,在通过nativequery= true
@query
注解也可以执行insert语句 - 可以通过传入
entity
参数,在sql语句中使用:#{% raw %}{#entity}{% endraw %}
来调用实体类的属性,注意一定要加冒号 - 在sql语句中,直接插入entity的uuid,就不会执行基类的
@Generator
,也就能保持和XML文件中UUID一致
该错误在控制台会报,父类主键不存在,因为父类主键被篡改了,而子类存储父类UUID还是实体类中的UUID,所以报错,否则不容易发现
问题三:插入实体类的UUID时,出现了主键重复的错误
- 通过一步步溯源,可以发现在使用DOM解析时,有的节点被遍历的两遍
- 问题在于,为什么会遍历两遍?
- 我第一遍采用
Element.getElementByTagName()
方法,获取第一层,之后对以后的实体类进行递归遍历, - 这种方法实际上是遍历所有的子节点,包含子节点的子节点,并不是往下一层搜索
- 正确的用法是,采用
getChildNodes()
获取子节点组成的NodeList
,之后对NodeList
遍历,通过Node.getNodeName()
获取具体的某个孩子节点 Node
和Element
可以相互转型,通过getAttribut(String)
可以获取具体的某个属性的value
便于测试的方法
- 因为主键的数据无法重复插入,也就意味着对于同一XML文件,每次测试插入前,如果不删除上次的数据,就会报主键冲突的错误
- 可以把ddl-auto设置为auto,每次运行项目时,首先把全部的表都删除,然后重新建表,重新插入外键,最后插入全部值,每次都是新感
最后发现HEXO的一个小bug,不能{和#连用
- 以上用法会导致
Error: expected end of comment, got end of file
- 因为这种语法是nunjucks的注释,所以会导致错误
- 解决办法对于
{% raw %}{#{% endraw %}
用一个被{}和%包围的raw
作为开始,endraw
作为结束