目录
1.java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
2.Rolled back transaction for test
3.关于mybatis-plus创建时间createtime和更新时间updatetime为空null的问题
4.关于mybatis-plus的乐观锁不起作用,无法实现自增
5.in a frame because it set 'X-Frame-Options' to 'deny'
6.zTree的zNodes报错Cannot read property 'substring' of undefined
1.java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
故障原因:
- JAXB API是java EE 的API,因此在java SE 9.0 中不再包含这个 Jar 包。
- java 9 中引入了模块的概念,默认情况下,Java SE中将不再包含java EE 的Jar包
- 而在 java 6/7 / 8 时关于这个API 都是捆绑在一起的
解决方法:
- 解决方案一: 降低JDK 版本到 JDK 8
解决方案二:(推荐,亲测可行)导入jaxb-api依赖
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
2.Rolled back transaction for test
在SpringBootTest中进行 `@Transactional` 注解的测试,会默认开启`@rollback(true)`,如下面代码的第一行最后部分,所以无论代码执行是否成功都会回滚。
详细说明参考:https://blog.csdn.net/jinbaizhe/article/details/81055495
2021-01-27 10:45:21.479 INFO 13788 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@5965be2d testClass = SpringbootApplicationTests, testInstance = com.shuang.SpringbootApplicationTests@3ccfac29, testMethod = contextLoads@SpringbootApplicationTests, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@409c54f testClass = SpringbootApplicationTests, locations = '{}', classes = '{class com.shuang.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@ba54932, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@343570b7, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@76f2bbc1, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@152aa092, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@51f116b8, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@2812cbfa], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.jdbc.support.JdbcTransactionManager@5c41b8d8]; rollback [true]
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@119f072c]
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@85c3522] will be managed by Spring
==> Preparing: INSERT INTO login ( user_id, user_id_number, user_password, user_role, gmt_create, gmt_update ) VALUES ( ?, ?, ?, ?, ?, ? )
==> Parameters: 2(Integer), 2(Integer), 2(String), admin(String), null, null
<== Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@119f072c]
true
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@119f072c]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@119f072c]
2021-01-27 10:45:22.314 INFO 13788 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@5965be2d testClass = SpringbootApplicationTests, testInstance = com.shuang.SpringbootApplicationTests@3ccfac29, testMethod = contextLoads@SpringbootApplicationTests, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@409c54f testClass = SpringbootApplicationTests, locations = '{}', classes = '{class com.shuang.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@ba54932, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@343570b7, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@76f2bbc1, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@152aa092, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@51f116b8, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@2812cbfa], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]
3.关于mybatis-plus创建时间createtime和更新时间updatetime为空null的问题
mybatis-plus官方地址:https://mp.baomidou.com/guide/auto-fill-metainfo.html
实现 mybatis-plus 的 MetaObjectHandler 自动填充处理器接口,需要注意的是官方的示例给的是 LocalDateTime.class 和 LocalDateTime.now(),但是实体类 entity 给的是 date 类型,所以类型不匹配,导致填充为空 null。如下代码只是修改好后的代码,Data.class 和 new Date() 代替了官方的示例,如果想了解更多,请移步到 mybatis-plus 官网。
package com.shuang.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Date;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("[执行[insertFill]->插入填充]");
this.strictInsertFill(metaObject, "gmtCreate",Date.class,new Date()); // 起始版本 3.3.0(推荐使用)
this.strictInsertFill(metaObject, "gmtUpdate", Date.class,new Date()); // 起始版本 3.3.0(推荐使用)
// 或者
}
/**
* 更新自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("[执行[updateFill]->修改填充]");
this.strictUpdateFill(metaObject, "gmtUpdate", Date.class, new Date()); // 起始版本 3.3.0(推荐)
}
}
4.关于mybatis-plus的乐观锁不起作用,无法实现自增
mybatis-plus官方文档:https://mp.baomidou.com/guide/interceptor-optimistic-locker.html#optimisticlockerinnerinterceptor
首先要在 MybatisPlusConfig 配置里面注册乐观锁插件
package com.shuang.config;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
@Configuration
@MapperScan("com.shuang.mapper")
public class MybatisPlusConfig {
/**
* 注册乐观锁
* @return
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
其次在修改之前一定一定要先查询此数据,官方也明确说明了,在所要修改的实体类里面一定一定要带上查出来的version,把version赋值给所要修改的实体,在执行sql语句时会帮我们实现自增,我们无需手动自增。
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
package com.shuang;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shuang.entity.Login;
import com.shuang.service.LoginService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest
class SpringbootApplicationTests {
@Autowired
private LoginService loginService;
@Test
void contextLoads() {
QueryWrapper<Login> wrapper = new QueryWrapper<>();
wrapper.eq("user_id_number",2);
Login login = loginService.getOne(wrapper); // 查询要修改的数据
login.setUserId(2);
login.setUserIdNumber(2);
login.setUserPassword("2");
login.setUserRole("member");
boolean result = loginService.updateById(login); // 修改数据
System.out.println(result);
}
}
5.in a frame because it set 'X-Frame-Options' to 'deny'
被Security管理的接口中,其中可能包含html页面,而前端在开发时,可能使用frame标签。为了系统安全性,默认情况下X-Frame-Options是禁止的。
某博客详解:此处是超链接
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.headers().frameOptions().sameOrigin()
//.and()... more config
;
// @formatter:on
}
6.zTree的zNodes报错Cannot read property 'substring' of undefined
因为后端controller传给前端的是json格式,需要用JSON.parse()转换成对象格式,上代码。
//controller部分代码
@RequestMapping("/showAddRole")
public String showAddRole(Model model) {
JSONArray jsonArray = permissionService.getTreeUtil(0);
model.addAttribute("menus", jsonArray.toJSONString());
return "/employee/role/addrole";
}
//前端部分代码
<script th:inline="javascript">
var setting = {
check: {
enable: true
},
data: {
simpleData: {
enable: true
}
}
};
zNodes = JSON.parse([[${menus}]]);
$(document).ready(function(){
$.fn.zTree.init($("#treeDemo"), setting, zNodes);
});
</script>