Mybatis面试题(总结最全面的面试题!!试题qq西游打怪源码!码面)
数据持久化概念指的试题是将数据从一种持久状态转换为另一种持久状态的过程。在编程中,码面数据持久化主要应用于将数据从内存状态持久化到磁盘或者数据库等非内存存储介质中,试题反之亦然。码面 Mybatis是试题一个基于Java的持久层框架,它将SQL语句和Java代码分离,码面实现数据与程序逻辑的试题解耦。Mybatis遵循ORM(对象关系映射)思想,码面将Java对象与数据库表对应,通过XML配置或注解实现对数据库的访问。它有以下优点:灵活性高,支持定制SQL语句,适用于复杂和动态的数据库操作。
性能较好,Mybatis避免了JDBC重复创建和关闭连接的开销。
易于学习和使用,语法简单明了。
然而,Mybatis也存在以下缺点:配置相对复杂,尤其是对动态SQL的支持需要一定技巧。
不够安全,如果处理不当,可能导致SQL注入等问题。
集成度较高,需要与Spring等框架配合使用。
Mybatis与Hibernate相比,最大的不同在于Mybatis采用XML文件或注解进行配置,而Hibernate使用Java注解或基于XML的HQL进行配置。此外,Mybatis支持手动编写SQL语句,而Hibernate依赖于HQL。 #{ }和${ }的区别主要在于参数化处理。#{ }使用预编译参数,可以有效防止SQL注入;${ }直接输出变量值,存在安全风险。 当实体类中的属性名和表字段名不一致时,可以通过XML映射文件中的``标签进行属性与字段的映射。 模糊查询时,可以使用`like`语句配合通配符实现,例如`%`。 Dao接口的工作原理是通过执行预编译的SQL语句来实现对数据库的操作。接口中的方法可以重载,但参数必须不同。 Mybatis分页通过实现插件机制,动态生成分页SQL来实现。分页插件原理涉及动态SQL生成。 Mybatis将SQL执行结果封装为目标对象,通过映射文件中的``或``标签实现。映射形式包括基本类型、复合类型、自定义类型等。 动态SQL主要作用在于提高SQL的灵活性,支持条件的视频播放源码php动态添加、修改和删除。动态SQL执行原理涉及解析SQL语句,生成动态SQL代码。 MyBatis的Xml映射文件中,不同Xml映射文件的ID可以重复,但实际操作中应避免重复,以避免混淆。 MyBatis是半自动ORM映射工具,与全自动的ORM框架相比,它需要手动编写部分SQL语句,但提供了更高的灵活性和控制。 MyBatis实现一对多关系通常采用两种方式:嵌套查询和嵌套结果。嵌套查询使用子查询实现,嵌套结果则将多对一关系映射为单个实体。 MyBatis支持延迟加载,通过配置延迟加载属性实现。其原理是将对象加载延迟到实际使用时,从而减少初始加载的开销。 Mybatis的一级缓存和二级缓存分别针对会话(Session)和全局范围内缓存对象,提高了数据访问效率。 接口绑定是指将多个方法绑定到一个接口上,实现单一入口调用。MyBatis中通过接口绑定实现,允许通过接口统一调用多个方法。 使用MyBatis的mapper接口调用时,主要要求是正确配置mapper文件和接口,以及保证方法名和mapper文件中方法名称对应。 Mybatis通过预编译语句和参数绑定来防止SQL注入,确保数据安全。Mybatis面试题
知乎的排版可能不好,而且颜色不够鲜明,我把它也整理到了我的网站,还有答主面试整理的高频题:
需要的可以访问: Java小白求职之路
1、MyBatis的工作原理
1)读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
2)加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
3)构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
7)输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
8)输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是淘宝评论晒图源码基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
2、Mybatis 缓存
Mybatis中有一级缓存和二级缓存,默认情况下一级缓存是开启的,而且是不能关闭的。
一级缓存是指 SqlSession 级别的缓存,当在同一个 SqlSession 中进行相同的 SQL 语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存 条 SQL。
二级缓存是指可以跨 SqlSession 的缓存。是 mapper 级别的缓存,对于mapper 级别的缓存不同的sqlsession 是可以共享的。
3、Mybatis 的一级缓存原理 ( sqlsession 级别 )
第一次发出一个查询 sql,sql 查询结果写入 sqlsession 的一级缓存中,缓存使用的数据结构是一个 map。
key:MapperID+offset+limit+Sql+所有的入参 value:用户信息
同一个 sqlsession 再次发出相同的 sql,就从缓存中取出数据。如果两次中间出现 commit 操作 (修改、添加、删除),本 sqlsession 中的一级缓存区域全部清空,下次再去缓存中查询不到 所以要从数据库查询,从数据库查询到再写入缓存。
4、二级缓存原理 ( mapper 级别)
二级缓存的范围是 mapper 级别(mapper同一个命名空间,Namespace),mapper 以命名空间为单位创建缓存数据结构,结构是 map。mybatis 的二级缓存是通过 CacheExecutor 实现的。CacheExecutor其实是 Executor 的代理对象。所有的查询操作,在 CacheExecutor 中都会先匹配缓存中是否存在,不存在则查询数据库。 key:MapperID+offset+limit+Sql+所有的入参
具体使用需要配置:
5、#{ }和${ }的区别是什么
#{ }是预编译处理,${ }是字符串替换。
Mybatis在处理#{ }时,会将sql中的#{ }替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${ }时,就是把${ }替换成变量的值。
使用#{ }可以有效的防止SQL注入,提高系统安全性。
预编译语句的优势在于归纳 为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止sql注入。
6、什么是MyBatis的接口绑定?有哪些实现方式?
接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式:
7、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是下载源码怎么用无法完成赋值的。
8、Mybatis一对一、一对多的查询
MyBatis 中使用collection标签来解决一对多的关联查询,collection标签可用的属性如下: property:指的是集合属性的值. ofType:指的是集合中元素的类型. column:所对应的外键字段名称. select:使用另一个查询封装的结果.
MyBatis 中使用association标签来解决一对一的关联查询,association标签可用的属性如下: property:对象属性的名称. javaType:对象属性的类型. column:所对应的外键字段名称. select:使用另一个查询封装的结果!
如:
个人觉得,发送一个sql去查询,使用List 作为回参也可以做到。
上面这段代码,也是面试经常问到的将sql执行结果封装为目标对象并返回,其实现的过程就是通过resultMap进行封装,而property和 column 进行映射,使数据库的列名和对象的名称对应。Mybatis也会智能匹配,比如可以指定驼峰,如果找不到映射对应的关系,就是默认值。
9、Mybatis的分页原理
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的原理就是使用MyBatis提供的插件接口,实现自定义插件,在插件的拦截方法内,拦截待执行的SQL,然后根据设置的dialect(方言),和设置的分页参数,重写SQL ,生成带有分页语句的SQL,执行重写后的SQL,从而实现分页。
举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,
、什么是Mybatis的动态SQL?
1) 传统的JDBC的方法,在组合SQL语句的时候需要去拼接,稍微不注意就会少少了一个空格,标点符号,都会导致系统错误。Mybatis的动态SQL就是为了解决这种问题而产生的;Mybatis的动态SQL语句值基于OGNL表达式的,方便在SQL语句中实现某些逻辑;可以使用标签组合成灵活的sql语句,提供开发的效率。
2) Mybatis的动态SQL标签主要由以下几类: If语句(简单的条件判断) Choose(when/otherwise),相当于java语言中的switch,与jstl中choose类似 Trim(对包含的内容加上prefix,或者suffix) Where(主要是用来简化SQL语句中where条件判断,能智能的处理and/or 不用担心多余的语法导致的错误) Set(主要用于更新时候) Foreach(一般使用在mybatis in语句查询时特别有用)
其他面试题:
年轻人,到这里你是否头秃了! 年轻人不讲武德,耗子尾汁是不可能的。
需要资源的可点这里(思维导图+Java学习路线+入门视频+框架视频+简历模板+面试题):
mybatis常见面试题有哪些?
MyBatis是一款广受欢迎的持久层框架,尤其在中国有着广泛的应用,常与Spring和Mybatis结合使用,简称为SSM组合中的M。
MyBatis的强项之一是动态SQL支持,大幅减少了编写JDBC代码的繁琐,避免了手动设置参数和处理结果集的麻烦。动态SQL特性使得根据不同的ue3源码条件拼接SQL语句变得简单且高效。
在MyBatis中,可以使用两种符号进行动态SQL的拼接:${ } 和 #{ }。虽然两者功能相似,但它们在使用上有显著的区别。
基本用法上,#和$都可以用于动态SQL拼接。使用$时,会在SQL字符串中多加一对单引号,这实际上是将SQL语句视为普通字符串。而#则是预处理语句的符号,用于代替参数。区别在于,使用#可以避免SQL注入风险,因为它将参数当作SQL语句的一部分,而非直接插入到SQL中,从而防止恶意的SQL注入攻击。
SQL注入是当用户输入的参数在生成SQL语句时未得到适当处理时,攻击者可以注入恶意的SQL代码,导致非预期的数据库操作。一个简单的例子可以说明这个问题:假设有一个查询语句,要求根据用户名和密码查询用户是否存在。如果参数未得到安全处理,恶意用户可以输入如`' or 1=1 --`这样的参数,即使用户名部分是正确的,整个查询语句实际上变成了一个永远返回真值的语句,这即为SQL注入。
为了避免SQL注入,通常不推荐使用$符号拼接SQL语句,而应使用#符号。因为使用#可以确保参数被正确地作为参数处理,而非作为SQL语句的一部分。
在某些特殊情况下,如将数据库对象作为参数传递,特别是当字段名不确定时(例如在分组排序查询中),只能使用$符号。这是因为#预处理之后会将数据库字段名识别为字符串,可能导致错误。
总结来说,#符号在MyBatis中提供了额外的安全性,避免了SQL注入的风险。在大多数情况下,推荐使用#符号进行动态SQL的拼接。而当需要将数据库对象作为参数传递时,则需要使用$符号。
道MyBatis面试题总结,看完你还敢说懂MyBatis吗?
本文总结了个MyBatis面试中的关键问题,帮助你检验对MyBatis的理解深度。通过这些问题,你可以了解#{ }和${ }的区别,XML映射文件的复杂标签,Dao接口的工作原理,分页方法,动态SQL的使用,对象映射及关联查询,延迟加载机制,Executor执行器的选择,枚举类映射,标签引用的处理,以及MyBatis与Spring Data JPA的对比。MyBatis作为一款灵活且易于操作的持久层框架,适合快速响应需求变化的项目,而Hibernate则以其全面的封装和较好的移植性,适合对关系模型要求高的场景。掌握这些知识点,将有助于你在面试中展示扎实的MyBatis技能。
MyBatis最新面试题汇总(只看这篇就够了)
MyBatis的优缺点
优点:一是基于 SQL 语句编程,具有高度灵活性,且与程序代码分离,便于统一管理;二是与JDBC相比,大幅减少代码量,降低了维护成本,避免了JDBC代码的冗余;三是提供XML标签支持动态SQL,便于重用和调整;四是能与各种数据库兼容,借助JDBC实现。
缺点:一是在编写SQL语句时对开发者的功底要求较高;二是SQL语句的变动可能导致数据库移植性问题。
${ }与#{ }的区别
${ }执行字符串替换,而#{ }则通过预编译处理SQL,能有效防止SQL注入,提高系统安全性。
解决JDBC编程不足之处的方法
1)使用数据库连接池管理连接,避免资源浪费和性能影响,通过在SQLMapConfig.xml中配置连接池解决。
2)将SQL语句配置在mapper.xml文件中,与JAVA代码分离,提高代码维护性。
3)利用#{ }参数传递方式,避免SQL注入风险,提高安全性。
4)自动将JAVA对象映射为SQL执行结果,简化结果集解析过程。
处理实体类属性与表字段不一致的方法
通过定义字段别名或配置映射关系,确保属性名与字段名一致。
MyBatis编程步骤
1、创建SQLSessionFactory
2、使用SQLSessionFactory创建SQLSession
3、通过SQLSession执行数据库操作
4、调用session.commit()提交事物
5、调用session.close()关闭会话
模糊查询的实现
使用like %xx%结构,推荐使用字符串拼接函数避免错误。
使用Mybatis的mapper接口调用要求
确保接口方法名、输入参数类型和结果类型与mapper.xml文件中的SQL相匹配,且namespace与接口全限定名一致。
实现动态SQL的方法
MyBatis通过接口的全限定名和方法名匹配MapperStatement对象,实现SQL动态生成。
分页机制与插件原理
使用RowBounds对象进行内存分页,插件通过拦截方法重写SQL,实现物理分页功能。
MyBatis常用注解与映射形式
通过标签和列别名实现对象属性与数据库列的映射,利用反射创建并赋值。
其他标签与动态SQL
除常见标签外,还包括用于逻辑判断、条件组合等功能的标签。
MyBatis插件运行原理与编写
通过JDK动态代理实现接口方法拦截,配置插件注解以指定拦截方法。
支持延迟加载的机制与原理
在配置文件中启用,使用CGLIB创建代理对象,动态生成查询关联对象的SQL。
映射文件与内部数据结构关系
Xml配置信息封装至Configuration对象,标签解析为不同类型对象,最终形成MappedStatement。
Mybatis面试题总结及答案
Mybatis是一个半对象关系映射(ORM)框架,它的核心是简化JDBC的复杂性,程序员编写原生SQL,能精确控制性能,提供灵活性。它通过XML或注解配置SQL语句和对象映射,避免了大部分JDBC代码,自动处理数据绑定和结果集映射。
Mybatis的优点主要体现在:SQL语句编写灵活,与JDBC相比减少代码量,支持多种数据库,与Spring集成良好,以及提供ORM映射支持。然而,它对SQL编写要求较高,依赖数据库设计,移植性较差。
适用于对SQL性能要求高或项目需求频繁变化的场景,如互联网应用。Mybatis与Hibernate的区别在于:Mybatis需要手动编写SQL,更适合对关系模型要求不高的项目;而Hibernate提供更强的ORM能力,支持数据库无关性。
在使用Mybatis时,#{ }用于预编译防止SQL注入,${ }则是字符串替换。当实体类属性名与表字段不同时,可通过别名或映射配置解决。模糊查询时,可通过Java代码或SQL拼接处理,但后者需注意防止SQL注入。
Mapper接口与XML映射文件紧密关联,接口方法和XML的id、参数类型、返回类型需对应。Mybatis通过JDK动态代理实现分页,使用RowBounds对象进行内存分页或插件进行物理分页。插入操作支持批量,通过预定义的insert语句执行。
Mybatis通过映射标签将查询结果映射到对象,支持多种映射形式。一对一和一对多关联查询需要手动编写SQL,可通过联合查询或嵌套查询实现。它支持延迟加载,通过CGLIB创建代理对象在需要时动态查询。
Mybatis的缓存机制包括一级缓存(Session级)和二级缓存(Mapper级),可配置启用。接口绑定提供了灵活性,通过注解或XML绑定SQL语句。使用mapper接口时,需注意方法名、参数类型和结果类型的一致性。
编写Mapper接口的方式有多种,如继承SqlSessionDaoSupport,使用MapperFactoryBean,或扫描器自动扫描。插件是Mybatis的扩展机制,通过拦截器实现对特定接口方法的拦截和定制。
道经典 MyBatis 面试题
Mybatis是一个半ORM框架,简化JDBC复杂性,支持动态SQL,提供映射标签实现对象关系映射,减少SQL编写工作量,减少代码量,兼容多种数据库,与Spring整合良好,提供ORM灵活性,支持对象与数据库之间的映射关系,提高编码效率。
Mybatis优点包括基于SQL语句编程,提供XML标签支持动态SQL,减少JDBC代码量,易于与各种数据库兼容,与Spring集成,提供对象关系映射,支持对象关系维护。
缺点涉及SQL编写工作量大,数据库移植性受限,Mybatis不支持数据库无关性,若需在不同数据库间切换,需自定义SQL映射文件,工作量大。
适用场合为性能需求高或需求变化频繁的项目,如互联网应用开发。
Mybatis与Hibernate的不同在于Mybatis需要手动编写SQL,灵活性高,而Hibernate具备更强大的对象关系映射能力与数据库无关性,适合关系模型要求高的软件开发。
#{ }和${ }的区别在于#{ }预编译处理,${ }进行字符串替换,使用#{ }可有效防止SQL注入,提高安全性。
处理实体类属性与表字段名不一致问题,可通过定义字段别名或配置字段映射。
模糊查询like语句可以通过Java代码或SQL语句添加通配符,注意避免SQL注入。
Xml映射文件中,Dao接口全限名作为映射文件namespace值,接口方法名作为Statement id值,参数对应方法内参数。接口方法由JDK动态代理实现,通过映射文件定位MapperStatement执行SQL。
Mybatis支持分页,通过RowBounds对象进行内存分页,也可使用插件实现物理分页。
Mybatis通过标签完成SQL执行结果封装,支持列名与属性名映射,或使用列别名实现。
批量插入可通过预定义的insert语句实现,使用批处理方法执行。
自动生成主键值时,insert方法返回插入行数,若采用自增策略,主键可设置到传入参数中。
在mapper中传递多个参数可通过多种方式实现,包括标签、注解或封装map。
Mybatis动态SQL提供条件判断、循环、选择等逻辑处理,通过标签实现动态SQL生成。
Mybatis除了常见操作标签,还支持Xml映射文件中引入sql片段、配置主键生成策略。
Xml映射文件中id重复规则取决于是否配置了namespace,namespace不同则id可以重复。
Mybatis被称为半自动ORM映射工具,与全自动ORM工具如Hibernate的区别在于手动编写SQL。
一对一关联查询使用association节点配置,一对多关联查询使用collection节点配置。
Mybatis实现一对多关联查询通过联合查询和嵌套查询,联合查询一次查询多个表,嵌套查询先查询主表,再根据外键关联查询子表。
Mybatis支持延迟加载,实现原理通过CGLIB创建代理对象,在调用对象方法时动态生成SQL查询关联对象,实现延迟加载。
Mybatis缓存机制分为一级和二级缓存,一级缓存基于Session本地存储,二级缓存基于Namespace存储,可自定义缓存源。
接口绑定通过注解或XML配置实现,注解适用于简单SQL,XML适用于复杂SQL。
Mapper接口调用要求包括接口实现、实现类、XML配置以及Spring整合。
Mapper编写方式有SqlSessionDaoSupport继承、MapperFactoryBean配置、MapperScanner配置等。
Mybatis插件运行原理基于动态代理,通过实现Interceptor接口并指定拦截接口与方法,可在执行特定接口方法时动态生成SQL或执行其他操作。
道不得不会的MyBatis面试题
本系列《最少必要面试题》
1. 什么是MyBatis?
这个问题主要是对比JDBC来看,MyBatis是一个基于Java的持久层框架,它将SQL语句与Java代码分离,通过XML或注解配置来实现数据库操作,简化了开发过程。
2. MyBatis的优点
MyBatis的优点包括配置简单、SQL语句执行效率高、易于维护、灵活性强等。
3. #{ }和${ }的区别是什么?
Mybatis在处理#{ }的时候会将sql中的#{ }替换成?号,调用PreparedStatement来赋值;Mybatis在处理${ }替换成变量的值,调用Statement来赋值。
4. 一个 Xml 映射文件,都会写一个 Dao 接口与之对应,这个 Dao 接口的工作原理是什么?
Dao 接口就是人们常说的 Mapper 接口,接口的全限名,就是映射文件中的 namespace 的值,接口的方法名就是映射文件中MappedStatement 的 id 值,接口方法内的参数就是传递给 sql 的参数。接口里的方法是不能重载的,因为是全限名+方法名的保存和寻找策略。Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行接口方法所对应的MappedStatement所代表的sql,然后将sql执行结果返回。
5. 如何获取自动生成的(主)键值?
用法:在 标签中添加 useGeneratedKeys="true" 等属性。当 Mybatis 解析 xml节点是,读到insert 有配置时,会判断是否 有配置 useGeneratedKeys,如果有则会使用 Jdbc3KeyGenerator 作为sql回显,否则会以 NoKeyGenerator 作为主键回显。底层封装了JDBC获取自增主键,即当使用 prepareStatement 或者 Statement时候,可以通过getGeneratedKeys 获取 当条插入语句的自增而成的主键。
6. Mybatis 动态 sql 有什么用?有哪些动态 sql?执行原理?
Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。Mybatis 提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。
7. 什么是Mybatis的一级、二级缓存?
一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 将清空。二级缓存与一级缓存其机制相同,不同在于其存储作用域为 Mapper(Namespace)。即使开启了二级缓存,不同的sqlsession之间的缓存数据也不是想互访就能互访的,必须等到sqlsession关闭了以后,才会把其一级缓存中的数据写入二级缓存。
8. MyBatis的工作原理
一图胜千文
9. 什么是MyBatis的接口绑定?有哪些实现方式?
接口绑定,就是在 MyBatis 中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。接口绑定有两种实现方式。
. Mybatis的分页原理
Mybatis 使用 RowBounds 对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,所以一般不会使用。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。分页插件的原理就是使用 MyBatis 提供的插件接口,实现自定义插件,在插件的拦截方法内,拦截待执行的SQL,然后根据设置的 dialect(方言),和设置的分页参数,重写SQL ,生成带有分页语句的SQL,执行重写后的SQL,从而实现分页。
2024-11-14 10:47
2024-11-14 10:10
2024-11-14 10:05
2024-11-14 09:44
2024-11-14 08:49