目录
1.10 this.$router.push(参数) 实现页面跳转
1.12 request.get().then()函数的用法和作用
1.13 Vue Router中用于访问当前路由的查询参数(query parameter)的语法
1.14 this.$router和 this.$route的区别
3.1.2 @Controller和@RestController
3.1.6 @PostMapping、@GetMapping、@PutMapping的区别
3.7 BeanUtils.copyProperties()函数
3.8.4 Exception e中e.getMessage()、e.toString()、e.printStackTrace()的区别
4.1.1 在resource文件夹中设置mapper文件夹用于存放xml文件
4.1.2 在springboot中配置mybatis的mapper位置
5.3 CURRENT_TIMESTAMP和CURRENT_TIME的区别
1 vue相关
1.1 创建vue项目时的babel是什么
Babel是一个广泛使用的JavaScript编译器。它可以将最新版本的JavaScript代码转换为向后兼容的版本,以便在不同浏览器和环境中运行。在vue中,Babel通常用于将ES6+的JavaScript代码转换为ES5代码,以确保在旧版浏览器中也能正常运行。Vue CLI(命令行界面)通常会默认集成Babel,以便在Vue项目中使用最新的JavaScript语法
1.2 vue中的组件
在vue中,通常将用户界面分解成多个组件,这些组件包括视图组件(views)和功能组件(components)。视图组件通常同于表示整个页面或页面的一部分,而功能组件则用于表示页面中的具体功能或元素
视图组件(views)通常用于表示整个页面或页面的一部分,他们通常包含路由和数据获取的逻辑。视图组件负责将数据传递给功能组件,并将它们组合在一起以呈现完整的界面。
功能组件(components)则用于表示页面中的具体功能或元素,如导航栏、表单、模态框等。它们通常是可复用的,可以在多个视图组件中使用。
在Vue中,视图组件和功能组件之间通过props(属性)和events(事件)进行通信。父级组件可以通过props将数据传递给子组件,子组件可以通过events将数据传递回父级组件。这种组件之间的通信机制使得代码更加模块化和可维护,同时也使得组件可以被复用在不同的上下文中。
总的来说,视图组件和功能组件在vue中是相互配合的,通过props和events进行通信,以构建复杂的用户界面。
1.3 vue中的app.vue是什么
App.vue是vue.js项目中的根组件,它包含了整个应用程序的基本结构和布局。在app.vue中,通常包含了应用程序的导航栏、侧边栏、页脚等全局的组件和布局,以及应用程序的路由和状态管理等全局配置。同时,app.vue也可以包含一些全局的样式和全局的逻辑处理,以及一些全局的生命周期钩子函数等。因此,app.vue可以看作是整个应用程序的入口和框架。
1.4 vue中的main.js是什么
在Vue.js项目中,通常会有一个名为main.js的文件,它是整个应用程序的入口文件。在main.js中,会包含应用程序的初始化逻辑,包括创建Vue实例、配置全局插件、注册全局组件、设置路由、状态管理等等。通常,main.js会引入根组件App.vue,并将其挂载到DOM中的某个元素上,从而启动整个Vue应用程序。因此,main.js可以被认为是Vue应用程序的主要控制文件,它负责整个应用程序的初始化和配置。
1.5 生命周期函数
此处有待进一步学习
1.6 axios处理前后端交互数据(优于fetch)
此处有待进一步学习
axios封装
import axios from 'axios' const request = axios.create({ baseURL: 'http://localhost:9090', /* baseURL: '/api', 注意!!这里是全局统一加上了/api 前缀,也就是说所有接口都会加上'/api前缀,在页面里面写接口的时候就不要加,/api 否则会出现2个"/api".类似"/api/api/user这样的报错,切记!!*/ timeout: 5000 }) // request 拦截器 // 可以自请求发送前对请求做一些处理 // 比如统一加token,对请求参数统一加密 request.interceptors.request.use( config => { config.headers['Content-Type'] = 'application/json;charset=utf-8'; // config.headers['token'] = user.token; // 设置请求头 return config }, error => { return Promise.reject(error) }); // response 拦截器 // 可以在接口响应后统一处理结果 request.interceptors.response.use( response => { let res = response.data // 兼容服务端返回的字符串数据 if (typeof res === 'string') { res = res ? JSON.parse(res) : res } return res; }, error => { console.log('err' + error) // for debug return Promise.reject(error) } )
1.7 导入 axios 库的2种方式
import {request} from "axios"; import request from "@/utils/request";
import { request } from "axios";
: 这是标准的 ES6 模块导入语法,它从 "axios" 模块中导入了名为request
的变量。这意味着你可以直接使用request
变量来调用 axios 提供的功能,例如发送 HTTP 请求等。
import request from "@/utils/request";
: 这是从自定义模块中导入默认导出的方式。假设 "@/utils/request" 是一个自定义的模块,它通过export default
导出了一个名为request
的对象或函数。在这种情况下,你可以直接使用request
变量来调用自定义模块中导出的功能。总的来说,第一种方式是从第三方模块中导入指定的变量,而第二种方式是从自定义模块中导入默认导出的变量。根据具体的情况,你可以选择适合你的场景的导入方式。
1.8 前端请求绑定
变量和事件缺一不可!
1.9 $notify通知插件
在Vue.js中,this.$notify.success() 表示使用 Vue 的通知插件来显示一个成功的通知。通常该方法会在某个操作成功完成后被调用,以向用户显示成功的消息。这个方法的具体实现可能依赖于具体使用的通知插件,但通常会在页面上显示一个成功的提示框或者消息条。
1.10 this.$router.push(参数) 实现页面跳转
很多情况下,我们在执行点击按钮跳转页面之前还会执行一系列方法,这时可以使用 this.$router.push(location) 来修改 url,完成跳转。
push 后面可以是对象,也可以是字符串:点击按钮跳转页面
1.11 URL中的查询参数
在这个地址中,问号(
?
)表示URL中的查询参数的起始位置,它用于将参数传递给服务器或客户端脚本。问号后面的部分是查询参数的键值对,键和值之间使用等号(=
)分隔,不同的键值对之间使用和号(&
)分隔。在这个地址中,
?
后面的部分是一个查询参数,它的键是id
,值是scope.row.id
。这个查询参数的作用是将scope.row.id
这个值传递给后端服务器或前端脚本进行处理。这个查询参数不会改变路由本身的名字,它只是在路由后面添加了一个查询参数。例如,如果原始路由是
/editUser
,那么添加了查询参数之后的完整URL可能是/editUser?id=123
,其中123
是scope.row.id
的值。在这个URL中,/editUser
是路由的名字,而?id=123
是查询参数,它的作用是将123
这个值传递给后端服务器或前端脚本进行处理。注scope:在Vue中,scope不是Vue自定义的属性,而是在使用Vue的表格组件时,用来指代当前行数据的一个内置变量。在使用Vue的表格组件(比如Element UI的表格组件)时,可以通过scope来访问当前行的数据。scope.row.id就是用来访问当前行的id属性。
1.12 request.get().then()函数的用法和作用
在JavaScript中,通常使用fetch API或类似的网络请求库来发起HTTP请求。其中,request.get().then()是一种常见的处理HTTP GET请求的方式。
request.get()是发起一个HTTP GET请求的方法,它通常接受一个URL作为参数,以及其他可选的配置参数,比如请求头、请求参数等。
then()是Promise对象的方法,用于处理异步操作的结果。在这种情况下,通常会将fetch请求返回的Promise对象传递给then()方法,以便在请求成功后执行相应的操作,比如处理响应数据、更新页面等。
1.13 Vue Router中用于访问当前路由的查询参数(query parameter)的语法
具体来说:
this.$route
是Vue Router中提供的用于访问当前路由信息的对象。.query
表示访问当前路由的查询参数部分。.id
表示访问查询参数中名为id的值。因此,整个代码的作用是从当前路由的查询参数中获取名为id的值,并将其赋给变量id。
1.14 this.$router和 this.$route的区别
在Vue.js中,this.$router和this.$route都是Vue Router提供的实例属性,用于处理路由相关的操作和信息获取。
this.$router:代表VueRouter的实例,可以通过this.router来执行编程式的路由导航,例如跳转到不同的路由或者获取路由的信息。
this.$route:代表当前活跃的路由对象,可以通过this.route来获取当前路由的信息,例如当前的路径、参数、查询参数等。
总结来说,this.$router用于路由的导舨,而this.route用于获取当前路由的信息。
1.15 show-password
"show-password"属性是Element UI中"el-input"组件的一个特定属性,用于实现密码框的显示/隐藏功能。
当"show-password"属性被设置为true时,输入框会显示密码明文,同时在输入框右侧会出现一个图标,用于切换密码的可见性。当"show-password"属性被设置为false时,输入框会显示密码的密文,同时图标也会隐藏。
1.16 路由中的 path: '*'
在Vue Router中,path: '*' 是一个通配符路径,它匹配所有路径。当没有其他路径与请求的路径匹配时,将会匹配到这个通配符路径。这通常用于创建一个“404 Not Found”页面,用来处理未知的路径或无效的路径。
总之,path: '*' 在Vue Router中表示一个通配符路径,用于匹配所有未知的路径或无效的路径。
1.17 路由守卫
比如说,当点击商城的购物车的时候,需要判断一下是否登录,如果没有登录,就跳转到登录页面,如果登陆了,就跳转到购物车页面,相当于有一个守卫在安检
路由守卫有三种:
1:全局钩子: beforeEach、 afterEach
2:独享守卫(单个路由里面的钩子): beforeEnter、 beforeLeave
3:组件内守卫:beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave
2 css相关
2.1 CSS中的position定位
1、static默认值,元素无设置的时候就是static
2、相对定位,对于当前位置进行调整。
3、absolute绝对定位,对于非static的父节点进行定位
4、固定浏览器绝对定位,对于浏览器进行定位。
5、粘性定位,介于相对与固定之间。top与滚动配合,滚前是relative,滚后是fixed这个最难理解,我们来个例子试试看吧
2.2 CSS中的calc()函数
calc() 函数允许在指定 CSS 属性值时执行计算。它对于计算 length、 percentage、 time、 numbers、integers、frequencies 和 angles 等特别有用。
CSS calc() 函数的一个强大功能是能够组合不同的单位。这个函数可以执行预处理器不能执行的数学计算。
3 Springboot框架
3.1 注解类
3.1.1 @RestController
使用@RestController注解的类可以处理HTTP请求并返回数据,通常用于构建RESTful风格的API
3.1.2 @Controller和@RestController
@Controller主要用于返回视图页面,通常配合模板引擎使用,例如Thymeleaf、Freemarker等。它会将方法返回的结果解析为视图页面的路径,并返回给客户端。
@RestController主要用于返回数据,通常配合JSON格式使用。它会将方法返回的结果直接作为JSON格式的数据返回给客户端,而不会解析为视图页面的路径。
@Controller和@RestController可以同时使用,但一般情况下它们不会存在包含关系。通常情况下,一个应用程序中会使用@Controller来返回视图页面,而@RestController用于返回数据。
在实际应用中,视图页面通常不包含JSON数据。视图页面主要用于呈现HTML、CSS和JavaScript等前端技术,而JSON数据通常由@RestController返回,用于前后端数据交互。如果需要在视图页面中包含JSON数据,可以通过AJAX等技术从后端获取JSON数据,然后在前端页面进行展示。
3.1.3 @Autowired和@Resource
@Autowired和@Resource注解的使用方式略有不同。
@Autowired注解默认按照类型(byType)进行自动装配,如果有多个类型相同的bean,会抛出NoUniqueBeanDefinitionException异常。如果要按照名称(byName)进行自动装配,需要结合@Qualifier注解使用。
而@Resource注解默认按照名称(byName)进行自动装配,如果找不到对应名称的bean,会抛出NoSuchBeanDefinitionException异常。
因此,如果您在使用@Autowired注解时遇到了NoUniqueBeanDefinitionException异常,可以尝试改用@Resource注解。但需要注意的是,@Resource注解的名称属性需要与被注入的bean的名称一致。如果名称不一致,也会抛出NoSuchBeanDefinitionException异常。
3.1.4 @RequestMapping
@RequestMapping注解是一个用来处理请求地址映射的注解,可用于映射一个请求或一个方法,可以用在类或方法上。
@RequestMapping详解_普通网友的博客-CSDN博客
3.1.5 @JsonFormat
@JsonFormat是Jackson库中的一个注解,用于指定Java对象序列化成JSON字符串时的格式。它可以用于日期、时间、数字等类型的字段上。
使用@JsonFormat注解时,需要指定一些属性,例如:
pattern:日期、时间格式的模式,比如yyyy-MM-dd HH:mm:ss;
shape:日期、时间格式的类型,可以是STRING、NUMBER、NUMBER_INT、 NUMBER_FLOAT、OBJECT等;
locale:使用的Locale;
timezone:时区。
此处在后端对时间进行了简单处理,不过该处理我们通常放在前端。
3.1.6 @PostMapping、@GetMapping、@PutMapping的区别
- @PostMapping用于创建新资源或提交表单数据;
- @GetMapping用于获取资源或查询数据;
- @PutMapping用于更新已存在的资源。
3.1.7 @Slf4j
1. 为什么使用@Slf4j?
@Slf4j是用来做日志输出的,用他就是为了能够少写两行代码,不用每次都在类的最前边写:
private static final Logger logger = LoggerFactory.getLogger(this.XXX.class);
我们只需要在类前面添加注解@Slf4j,即可使用log日志的功能了2. 怎么导入@Slf4j?
(1)首先,确保idea中有Lombok插件(IntelliJ IDEA 2020.3及以上版本已经内置Lombok plugin了,所以不需要安装插件,只需要在项目添加Lombok依赖就能用了)3.1.8 @Param
首先明确这个注解是为SQL语句中参数赋值而服务的。
@Param的作用就是给参数命名,比如在mapper里面某方法A(int id),当添加注解后A(@Param(“userId”) int id),也就是说外部想要取出传入的id值,只需要取它的参数名userId就可以了。将参数值传如SQL语句中,通过#{userId}进行取值给SQL的参数赋值。
3.2 lombok.Data
导入lombok.Data后,使用@Data可以自动在编译后生成模板代码,添加该注解,相当于自动添加了setter和getter方法,添加了toString方法,添加了equal和hashcode方法,添加了无参构造方法和相关参数的构造方法,使代码更加简洁
3.3 springboot的三层架构
【精选】Springboot三层架构--DAO层、Service层、Colltroler层--这波我在外太空_什么时候养猫猫的博客-CSDN博客
3.4 springboot跨域问题
在Web开发中,跨域指的是在浏览器中访问一个不同于当前域名的资源。浏览器出于安全考虑,限制了这种跨域资源的访问。具体来说,当浏览器使用XMLHttpRequest或Fetch API发送跨域请求时,目标服务器必须在响应头中包含特定的CORS(跨源资源共享)规则,否则浏览器会阻止该请求。
解决方法如下:
本次项目中使用注解来解决
3.5 注解和xml配置
使用注解还是XML配置取决于具体的需求和偏好。以下是一些情况下使用注解和使用XML配置的建议:
使用注解的情况:
- 简单的SQL映射:对于简单的SQL操作,可以使用注解来直接在映射器接口的方法上定义SQL语句,这样可以减少XML文件的数量,使代码更加简洁。
- 对于小型项目:在小型项目中,使用注解可以减少配置文件的数量,简化项目结构,更易于维护和理解。
使用XML配置的情况:
- 复杂的SQL映射:对于复杂的SQL操作,特别是涉及到动态SQL、复杂的结果映射等情况,使用XML配置可以更清晰地表达SQL映射,提高可读性和维护性。
- 需要与第三方系统集成:在需要与其他系统进行集成的情况下,使用XML配置可以更灵活地定义特定的配置,以适应不同系统的需求。
对于数据库操作,使用注解和XML配置都可以实现相同的功能,它们的性能和效果并没有明显的差异。因此,对于数据库操作的选择更多取决于开发团队的偏好和项目的具体需求。
在实际项目中,通常可以根据项目规模、团队经验、项目需求等因素来综合考虑,选择合适的配置方式。如果团队更熟悉注解方式,且项目比较简单,可以优先选择注解;如果项目比较复杂,或者需要与其他系统集成,可以考虑使用XML配置。同时,也可以在项目中灵活地结合使用注解和XML配置,以满足不同的需求。
本项目对数据库的操作使用注解方式
3.6 UserController中url路径的相关问题
"@GetMapping("/{id}")"中的大括号{}表示这是一个占位符,用来表示在URL中的动态参数。例如,如果URL是 "/user/123",那么{id}将会匹配到123这个值,这样就可以动态地获取不同的id值。
@PathVariable注解用来获取URL路径中的参数值,它告诉Spring框架将URL中的{id}部分的值赋给方法参数id。因此,@PathVariable Integer id表示将URL中的{id}部分的值赋给方法中的id参数,使得我们可以在方法中使用这个id值进行后续的操作。
3.7 BeanUtils.copyProperties()函数
BeanUtils.copyProperties的拷贝是浅拷贝,对基本数据类型进行值传递的属性复制,改变原基本数据类型的值不会改变被复制的属性结果;对引用数据类型进行引用传递的属性复制,只是复制了一个内存地址过去,指向的还是同一个对象,并没有新建对象,改变原对象的值,被复制的属性的值也会随着变化。
3.8 异常
3.8.1 全局异常处理
业务异常:
自定义这个异常,继承RuntimeException是为了方便查看来自service的异常,因为RuntimeException也可能存在于其他地方。
3.8.2 java中都有哪些异常
java中所有的异常都由Throwable继承而来,而后分为Error和Exception。
- Error:这种错误一般是系统错误或资源错误,用户一般无法解决
- Exception:又分为 “RuntimeException异常” 和 “非RuntimeException异常”
- RuntimeException异常 (运行期异常)
- 非RuntimeException异常 (编译器异常)
- 大多为IO流中的异常
- 因此,Exception:也常分为分为 “RuntimeException异常” 和 “IOException异常”
Java异常机制简述、RuntimeException与非RuntimeException的区别-CSDN博客
Java中常见的RunTime异常及异常详解_java.lang.runtimeexception: null-CSDN博客
3.8.3 SQLException
SQL异常主要有以下几种类型:
1 违反唯一约束异常、2 空值约束异常、3 数据类型不匹配异常、4 外键约束异常、5 语法错误异常
违反唯一约束异常:当违反唯一键或唯一索引约束时,会引发唯一约束异常。例如,试图向已经存在的唯一索引字段插入重复的值时,会引发该异常。
空值约束异常:当试图向不允许为空的字段插入空值时,会引发空值约束异常。例如,向定义了NOT NULL约束的字段插入空值时,会引发该异常。
数据类型不匹配异常:当试图向字段插入不符合数据类型要求的值时,会引发数据类型不匹配异常。例如,向整型字段插入字符串值时,会引发该异常。
外键约束异常:当试图向外键字段插入不存在的引用值时,会引发外键约束异常。例如,试图向外键字段插入不存在于主表的引用值时,会引发该异常。
语法错误异常:当SQL语句语法错误时,会引发语法错误异常。例如,缺少必要的关键字或者不正确的SQL语法都会引发该异常。
3.8.4 Exception e中e.getMessage()、e.toString()、e.printStackTrace()的区别
e.getMessage():返回异常的详细描述字符串。通常包含异常的原因和可能的解决方案。这个方法返回的是一个字符串。
e.toString():返回异常对象的字符串表示形式,通常包括异常类的名称和异常的描述信息。这个方法也返回一个字符串。
e.printStackTrace():将异常信息输出到标准错误流,通常用于调试目的。它会打印异常的类型、原因、以及异常出现的位置等信息。
总结来说,e.getMessage() 返回的是异常的描述信息字符串,e.toString() 返回的是异常对象的字符串表示形式,包括异常类的名称和描述信息,而 e.printStackTrace() 则是将异常信息输出到标准错误流,通常包括异常的类型、原因和出现位置。
4 mybatis相关
4.1 mybatis的xml配置注意事项
4.1.1 在resource文件夹中设置mapper文件夹用于存放xml文件
resultType处不能返回List<>,应返回一个对象。List<>是一个泛型类型,它表示一个元素类型为某个类的列表。resultType不能直接返回List<>,而应该返回列表中元素的类型。
在MyBatis中,resultType属性用于指定单个结果对象的类型,而不是列表类型。如果要返回列表类型的结果,应该使用resultMap来映射查询结果到列表类型的对象。
4.1.2 在springboot中配置mybatis的mapper位置
其中,classpath只的是resource文件夹。
4.2 mybatis的分页插件——pagehelper
4.2.1 pagehelper startPage()
pagehelper startPage()是MyBatis框架中的一个分页插件,用于开启分页功能。它的作用是在查询数据时,自动在SQL语句中添加分页的相关参数,从而实现数据的分页查询。
使用startPage()方法可以非常方便地实现数据分页功能,只需要在查询数据之前调用该方法,指定当前页码和每页显示的数据条数即可。例如:
PageHelper.startPage(int pageNum, int pageSize);
4.2.2 PageInfo
在Java中,尖括号(<>)表示泛型,用于指定一个类或方法的参数类型或返回值类型。在这段代码中,PageInfo<User>表示PageInfo是一个泛型类,泛型参数为User类型,即PageInfo是用于包装User类型数据的分页结果类。
当我们使用PageInfo进行分页包装时,需要将查询到的数据列表传递给PageInfo进行包装。在这里,我们可以直接将查询到的数据列表users作为参数传递给PageInfo的构造方法,如下所示:
PageInfo<User> userPageInfo = new PageInfo<>(users);
4.3 日志输出
4.3.1
log-impl配置
在MyBatis中,
log-impl
是用于配置日志输出的实现类的属性。 org.apache.ibatis.logging.stdout.StdoutImpl
是 MyBatis 提供的一个日志输出实现,它将日志信息输出到标准输出流(System.out)。当在配置文件中设置
logimpl
为org.apache.ibatis.logging.stdout.StdoutImpl
时,MyBatis 将使用标准输出流来输出日志信息。这通常用于调试和开发阶段,以便在控制台中查看 MyBatis 的日志输出。你也可以选择其他日志输出实现,比如将日志输出到日志文件或集成到其他日志框架中。这些都可以通过配置文件中的
log-impl
属性来指定。4.3.2 日志level
在日志系统中,
level: debug
表示日志级别为 DEBUG。不同的日志级别用来表示不同的日志信息重要程度,通常包括以下几个级别:
DEBUG:用于输出调试信息,通常包含详细的程序执行过程、变量状态等信息。在生产环境中一般不会输出 DEBUG 级别的日志,因为它们会产生大量的输出并可能暴露程序的内部细节。
INFO:用于输出一般信息,比如程序启动、关闭、关键流程等。INFO 级别的日志通常用于提示程序的运行状态。
WARN:用于输出警告信息,表示可能存在的问题或潜在的错误。WARN 级别的日志用于提示一些需要注意的情况,但并不一定是错误。
ERROR:用于输出错误信息,表示程序发生了错误或异常。ERROR 级别的日志通常用于记录程序的错误状态,以便后续排查问题。
当设置日志级别为
debug
时,日志系统会输出所有级别为 DEBUG、INFO、WARN 和 ERROR 的日志信息。这意味着在debug
级别下,所有级别的日志信息都会被输出。在实际应用中,可以根据需要调整日志级别,以便在不同的环境下输出不同级别的日志信息。
4.4 动态条件判断
MyBatis 的动态 SQL 功能来根据条件动态构建 SQL 查询语句。
在 SQL 中,你可以使用
CASE
表达式来实现类似于 MyBatis 中的动态条件判断。
4.5 参数绑定语法
在MyBatis中,#{}被用来表示一个占位符,用于将参数值动态地插入到SQL语句中。当SQL语句被执行时,#{}会被替换成实际的参数值,这样可以避免SQL注入等安全问题,并且可以方便地动态构建SQL语句。
4.6 resultType和resultMap的区别
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。
4.6.1 resultMap的用法
1 resultMap中的<id>和<result>是什么,有何区别?
resultMap中的<id>和<result>都是用来映射查询结果集中的字段到实体类中的属性。区别在于<id>用于标识查询结果集中的唯一标识字段,通常对应实体类中的主键属性,而<result>用于映射普通的字段,可以对应实体类中的普通属性。联系在于都是用来映射查询结果集中的字段到实体类中的属性,以便进行对象的映射和赋值操作。
2 resultMap里的<collection>
<collection>元素用于处理一对多的关联关系,它可以将一个查询结果集中的多行数据映射到一个集合类型的属性上。
在resultMap中,<collection>元素通常用于处理实体类中包含集合类型属性的情况,例如一个作者有多本书的情况。下面是一个示例:
<resultMap id="authorMap" type="Author"> <id property="id" column="author_id"/> <result property="name" column="author_name"/> <collection property="books" ofType="Book" select="selectBooksByAuthorId" column="author_id"/> </resultMap>
在上面的示例中,<collection>元素定义了一个名为"books"的集合属性,它指定了集合元素的类型为"Book",并且指定了一个select语句用于查询与作者相关的书籍。在实际查询时,MyBatis会自动执行select语句,并将查询结果映射到"books"属性上。
总之,<collection>元素可以帮助我们处理一对多的关联关系,将多行数据映射到集合属性上,从而方便地处理实体类中的复杂关联关系。
4.7 数据库下划线字段转驼峰
5 mysql相关
5.1 分页模糊查询
分页模糊查询是指在数据库中进行模糊匹配的同时,将查询结果分页返回给用户。通常情况下,分页模糊查询用于处理大量数据,以便用户能够浏览和检索大型数据集,而不会一次性将所有数据返回给用户。
具体来说,分页模糊查询通常包括以下几个步骤:
模糊查询:使用模糊查询语句(例如SQL中的
LIKE
语句)在数据库中查询符合条件的数据。模糊查询允许在查询中使用通配符来实现模糊匹配,例如在字符串中查找包含指定字符序列的数据。分页:将查询结果分割成多个页面,每个页面包含一定数量的数据条目。这通常通过在查询语句中添加
LIMIT
和OFFSET
子句来实现,例如LIMIT 10 OFFSET 0
表示返回第一页的10条数据,LIMIT 10 OFFSET 10
表示返回第二页的10条数据,依此类推。返回结果:将分页后的查询结果返回给用户,通常以列表或表格的形式展示在用户界面上,用户可以通过翻页或者其他交互方式浏览不同页面的数据。
分页模糊查询通常用于Web应用程序或者其他需要展示大量数据的场景,以提供更好的用户体验和减少数据传输的成本。
5.2 mysql 模糊查询 concat()的用法
在MySQL中,CONCAT函数用于将两个或多个字符串连接在一起。它的基本语法是CONCAT(str1, str2, ...),其中str1、str2等为要连接的字符串参数。
在上面的语句中,使用CONCAT('%',?1,'%')的目的是在参数?1的值前后各加上一个百分号(%)。在SQL中,百分号(%)通常用作通配符,表示任意字符(包括零个字符)。例如,如果参数?1的值为"abc",那么CONCAT('%',?1,'%')的结果就是"%abc%",表示匹配name字段中包含"abc"的任意位置的字符串。
这种用法通常用于实现模糊搜索,即在数据库中查找包含特定子字符串的记录。
5.3 CURRENT_TIMESTAMP和CURRENT_TIME的区别
CURRENT_TIMESTAMP
和CURRENT_TIME
都是 SQL 中用于获取当前时间的函数,但它们之间有一些区别。
CURRENT_TIMESTAMP
:
CURRENT_TIMESTAMP
函数返回当前日期和时间,包括年、月、日、时、分、秒和毫秒。它通常返回一个带有时区信息的时间戳。- 例如,
CURRENT_TIMESTAMP
可能返回类似于 "2023-11-21 13:30:45.123456 +00:00" 这样的时间戳,其中包含了日期、时间、毫秒以及时区信息。
CURRENT_TIME
:
CURRENT_TIME
函数返回当前的时间,包括时、分、秒和毫秒,但不包括日期信息。它通常返回一个带有时区信息的时间。- 例如,
CURRENT_TIME
可能返回类似于 "13:30:45.123456 +00:00" 这样的时间,其中只包含了时间、毫秒以及时区信息,没有日期信息。总的来说,
CURRENT_TIMESTAMP
返回包含日期和时间的完整时间戳,而CURRENT_TIME
只返回当前的时间部分,不包含日期信息。具体的返回格式和时区信息可能因数据库系统而异,因此在具体使用时需要查阅相应数据库的文档或规范。
5.4 Mysql order by 多字段排序
mysql单个字段降序排序:
select * from table order by id desc;
mysql单个字段升序排序:
select * from table order by id asc;
mysql多个字段排序:
select * from table order by id desc,name desc;
多字字段排序只需要添加多个排序条件,并且每个排序的条件之前用逗号分开。
表示先按照id降序排序,再按照name降序排序。
同理:
order by id desc,name asc;
表示先按照id降序排序,再按照name升序排序。
5.5 truncate和delete的区别
1.truncate
删除表中的内容,不删除表结构,释放空间;2.delete
删除内容,不删除表结构,但不释放空间3.区别
3.1内存空间
truncate删除数据后重新写数据会从1开始,而delete删除数据后只会从删除前的最后一行续写;内存空间上,truncate省空间3.2处理速度
因为,truncate是直接从1开始,即全部清空开始,而delete需要先得到当前行数,从而进行续写;所以truncate删除速度比delete快;3.3语句类型
delete属于DML语句,而truncate和drop都属于DDL语句,这造成了它们在事务中的不同现象:delete在事务中,因为属于DML语句,所以可以进行回滚和提交操作(由操作者)
truncate和drop则属于DDL语句,在事务中,执行后会自动commit,所以不可以回滚;3.4语法
delete from 表名 (where…可写可不写,写的话进行选择性删除,不选清空表中数据)truncate 表名(删除表中的数据,无法回滚的)
delete可以在后续加上where进行针对行的删除
truncate和drop后面只能加上表名,直接删除表,无法where
注意:并且drop和truncate不能够激活触发器,因为该操作不记录各行删除;drop table 表名
删除表,内容连带结构一起删除;
5.6 btree索引的底层数据结构
MySQL索引的底层数据结构原理剖析(二叉树、 红黑树、Hash、B-Tree、B+Tree)_mysql 二叉树-CSDN博客
5.7 自关联、左关联、右关联
自关联:在一个表中,某一列的值与该表中的另一列的值相关联的情况。例如,在一个员工表中,可以通过员工的上级ID与员工ID进行自关联,以确定每个员工的直接上级是谁。
左关联:左关联是指查询结果中包括左表中的所有记录,而右表中的匹配记录则根据条件进行匹配。例如,如果有一个订单表和一个客户表,左关联将返回所有订单,而对于每个订单,如果有匹配的客户,则返回匹配的客户信息,如果没有匹配的客户,则返回NULL。
右关联:右关联是指查询结果中包括右表中的所有记录,而左表中的匹配记录则根据条件进行匹配。与左关联相反,右关联将返回所有客户信息,对于每个客户,如果有匹配的订单,则返回匹配的订单信息,如果没有匹配的订单,则返回NULL。
同一个表和自己左关联:例如,在一个员工表中,可以通过员工的上级ID与员工ID进行自关联左关联,以确定每个员工的直接上级是谁,并返回包括员工和其直接上级的信息。
6 其他
6.1 设置uid
1. 在springboot配置文件中导入hutool工具
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,它帮助我们简化每一行代码,避免重复造轮子。如果你有需要用到某些工具方法的时候,可以在Hutool里面找找,可能就有你需要的工具方法。
Java基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类,同时提供许多组件,具体参考:
Hutool中 常用的工具类和方法_hutool常用方法-CSDN博客
在该项目中使用了日期工具和唯一ID工具。ps:还使用了加密工具
2. 在UserService中添加uid
1)UserService中通常用来聚合各种业务,所以代码添加在此处。
2)此外我们把该项目中的用户名当作uid来使用了,为了方便查看,我们在id前面加上创建时间共同组成uid。
3)由于自动生成的uid较长且含字母和数字,因此我们将其转换成哈希码用数字返回。
4)由于哈希码返回的值可能为负数,因此我们对他取一个绝对值。(注:可能会出现重复,可以使用雪花id或分布式id)待了解
6.2 数据校验
1. 使用Element中的表单验证组件
首先将model、rules、ref三个值与我们的表单绑定
其次在data中创建rules数组
然后在methods中创建 this.$res[form].validte() 函数
2. 自定义校验规则
Element提供了代码
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form-item label="密码" prop="pass"> <el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input> </el-form-item> <el-form-item label="确认密码" prop="checkPass"> <el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model.number="ruleForm.age"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button> <el-button @click="resetForm('ruleForm')">重置</el-button> </el-form-item> </el-form> <script> export default { data() { var checkAge = (rule, value, callback) => { if (!value) { return callback(new Error('年龄不能为空')); } setTimeout(() => { if (!Number.isInteger(value)) { callback(new Error('请输入数字值')); } else { if (value < 18) { callback(new Error('必须年满18岁')); } else { callback(); } } }, 1000); }; var validatePass = (rule, value, callback) => { if (value === '') { callback(new Error('请输入密码')); } else { if (this.ruleForm.checkPass !== '') { this.$refs.ruleForm.validateField('checkPass'); } callback(); } }; var validatePass2 = (rule, value, callback) => { if (value === '') { callback(new Error('请再次输入密码')); } else if (value !== this.ruleForm.pass) { callback(new Error('两次输入密码不一致!')); } else { callback(); } }; return { ruleForm: { pass: '', checkPass: '', age: '' }, rules: { pass: [ { validator: validatePass, trigger: 'blur' } ], checkPass: [ { validator: validatePass2, trigger: 'blur' } ], age: [ { validator: checkAge, trigger: 'blur' } ] } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } } </script>
6.3 Ctrl+r 替换文本
Word:选择该选项时,替换操作将只匹配整个单词,而不是部分匹配。例如,如果要替换“cat”这个单词,选择Word选项后,只有“cat”这个单词会被替换,而不会替换包含“cat”的其他单词,如“cater”或“category”。
Match case:选择该选项时,替换操作将区分大小写。例如,如果选择Match case选项,那么在替换时会区分“Cat”和“cat”。
Regex:选择该选项时,替换操作将使用正则表达式进行匹配和替换。正则表达式是一种强大的文本匹配工具,可以用来进行更复杂的匹配和替换操作,例如匹配多个模式、匹配特定位置的文本等。
因此,区别在于Word选项只匹配整个单词,Match case选项区分大小写,而Regex选项使用正则表达式进行更灵活的匹配和替换操作。
6.4 Session数据安全
有待学习
Session详解,学习Session,这篇文章就够了(包含底层分析和使用)_session级别-CSDN博客
6.5 用户密码加盐
6.6 JWT后端数据安全
SpringBoot集成JWT(极简版)_springboot+jwt-CSDN博客
6.7 小布尔和大布尔的区别
BOOL和bool的区别_qt中bool占用几个字节-CSDN博客
bool:if(admin.isstatus()) BOOL: if(admin.getstatus())
6.8 滑块验证
6.9 Element中table的树形数据
树形数据中指定row-key是为了唯一标识每一行数据,方便对数据进行查找、更新和删除操作。row-key指定的值可以是任何能唯一标识一行数据的值,比如唯一的ID、日期时间等。应该指定一个能够唯一标识数据的稳定且唯一的值,以确保数据的准确性和一致性。常见的row-key值包括自增的数字、UUID、时间戳等。