你买域名我送网站,国外网站做盗版,郴州seo公司,logo商标设计公司#{} 和 ${} 的区别是什么#xff1f;
答#xff1a;
${}是 Properties 文件中的变量占位符#xff0c;它可以用于标签属性值和 sql 内部#xff0c;属于原样文本替换#xff0c;可以替换任意内容#xff0c;比如${driver}会被原样替换为com.mysql.jdbc. Driver。
一个…#{} 和 ${} 的区别是什么
答
${}是 Properties 文件中的变量占位符它可以用于标签属性值和 sql 内部属于原样文本替换可以替换任意内容比如${driver}会被原样替换为com.mysql.jdbc. Driver。
一个示例根据参数按任意字段排序
select * from users order by ${orderCols}
orderCols可以是 name、name desc、name,sex asc等实现灵活的排序。
#{}是 sql 的参数占位符MyBatis 会将 sql 中的#{}替换为? 号在 sql 执行前会使用 PreparedStatement 的参数设置方法按序给 sql 的? 号占位符设置参数值比如 ps.setInt(0, parameterValue)#{item.name} 的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值相当于 param.getItem().getName()。 xml 映射文件中除了常见的 select、insert、update、delete 标签之外还有哪些标签
答还有很多其他的标签 resultMap、 parameterMap、 sql、 include、 selectKey 加上动态 sql 的 9 个标签 trim|where|set|foreach|if|choose|when|otherwise|bind 等其中 sql 为 sql 片段标签通过 include 标签引入 sql 片段 selectKey 为不支持自增的主键生成策略标签。 Dao 接口的工作原理是什么Dao 接口里的方法参数不同时方法能重载吗
答最佳实践中通常一个 xml 映射文件都会写一个 Dao 接口与之对应。Dao 接口就是人们常说的 Mapper 接口接口的全限名就是映射文件中的 namespace 的值接口的方法名就是映射文件中 MappedStatement 的 id 值接口方法内的参数就是传递给 sql 的参数。 Mapper 接口是没有实现类的当调用接口方法时接口全限名方法名拼接字符串作为 key 值可唯一定位一个 MappedStatement 举例com.mybatis3.mappers. StudentDao.findStudentById 可以唯一找到 namespace 为 com.mybatis3.mappers. StudentDao 下面 id findStudentById 的 MappedStatement 。在 MyBatis 中每一个 select、 insert、 update、 delete 标签都会被解析为一个 MappedStatement 对象。
Dao 接口里的方法是不能重载的因为是全限名方法名的保存和寻找策略。
Dao 接口里的方法可以重载但是 Mybatis 的 xml 里面的 ID 不允许重复。
Mybatis 版本 3.3.0亲测如下
/*** Mapper接口里面方法重载*/
public interface StuMapper {ListStudent getAllStu();ListStudent getAllStu(Param(id) Integer id);
}
然后在 StuMapper.xml 中利用 Mybatis 的动态 sql 就可以实现。
select idgetAllStu resultTypecom.pojo.Studentselect * from studentwhereif testid ! nullid #{id}/if/where
/select
能正常运行并能得到相应的结果这样就实现了在 Dao 接口中写重载方法。
Mybatis 的 Dao 接口可以有多个重载方法但是多个接口对应的映射必须只有一个否则启动会报错。
相关 issue更正Dao 接口里的方法可以重载但是 Mybatis 的 xml 里面的 ID 不允许重复。
Dao 接口的工作原理是 JDK 动态代理MyBatis 运行时会使用 JDK 动态代理为 Dao 接口生成代理 proxy 对象代理对象 proxy 会拦截接口方法转而执行 MappedStatement 所代表的 sql然后将 sql 执行结果返回。
补充
Dao 接口方法可以重载但是需要满足以下条件
仅有一个无参方法和一个有参方法多个有参方法时参数数量必须一致。且使用相同的 Param 或者使用 param1 这种
测试如下
PersonDao.java
Person queryById();Person queryById(Param(id) Long id);Person queryById(Param(id) Long id, Param(name) String name);
PersonMapper.xml
select idqueryById resultMapPersonMapselectid, name, age, addressfrom personwhereif testid ! nullid #{id}/ifif testname ! null and name ! name #{name}/if/wherelimit 1
/select
org.apache.ibatis.scripting.xmltags. DynamicContext. ContextAccessor#getProperty 方法用于获取 if 标签中的条件值
public Object getProperty(Map context, Object target, Object name) {Map map (Map) target;Object result map.get(name);if (map.containsKey(name) || result ! null) {return result;}Object parameterObject map.get(PARAMETER_OBJECT_KEY);if (parameterObject instanceof Map) {return ((Map)parameterObject).get(name);}return null;
}
parameterObject 为 map存放的是 Dao 接口中参数相关信息。
((Map)parameterObject).get(name) 方法如下
public V get(Object key) {if (!super.containsKey(key)) {throw new BindingException(Parameter key not found. Available parameters are keySet());}return super.get(key);
}
queryById()方法执行时parameterObject为 nullgetProperty方法返回 null 值if标签获取的所有条件值都为 null所有条件不成立动态 sql 可以正常执行。queryById(1L)方法执行时parameterObject为 map包含了id和param1两个 key 值。当获取if标签中name的属性值时进入((Map)parameterObject).get(name)方法中map 中 key 不包含name所以抛出异常。queryById(1L,1)方法执行时parameterObject中包含id,param1,name,param2四个 key 值id和name属性都可以获取到动态 sql 正常执行。
MyBatis 是如何进行分页的分页插件的原理是什么
答(1) MyBatis 使用 RowBounds 对象进行分页它是针对 ResultSet 结果集执行的内存分页而非物理分页(2) 可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能(3) 也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用 MyBatis 提供的插件接口实现自定义插件在插件的拦截方法内拦截待执行的 sql然后重写 sql根据 dialect 方言添加对应的物理分页语句和物理分页参数。
举例select _ from student 拦截 sql 后重写为select t._ from select \* from studentt limit 010
简述 MyBatis 的插件运行原理以及如何编写一个插件
答MyBatis 仅可以编写针对 ParameterHandler、 ResultSetHandler、 StatementHandler、 Executor 这 4 种接口的插件MyBatis 使用 JDK 的动态代理为需要拦截的接口生成代理对象以实现接口方法拦截功能每当执行这 4 种接口对象的方法时就会进入拦截方法具体就是 InvocationHandler 的 invoke() 方法当然只会拦截那些你指定需要拦截的方法。
实现 MyBatis 的 Interceptor 接口并复写 intercept() 方法然后在给插件编写注解指定要拦截哪一个接口的哪些方法即可记住别忘了在配置文件中配置你编写的插件。
MyBatis 执行批量插入能返回数据库主键列表吗
答能JDBC 都能MyBatis 当然也能。
MyBatis 动态 sql 是做什么的都有哪些动态 sql能简述一下动态 sql 的执行原理不
答MyBatis 动态 sql 可以让我们在 xml 映射文件内以标签的形式编写动态 sql完成逻辑判断和动态拼接 sql 的功能。其执行原理为使用 OGNL 从 sql 参数对象中计算表达式的值根据表达式的值动态拼接 sql以此来完成动态 sql 的功能。
MyBatis 提供了 9 种动态 sql 标签:
if/ifwhere/where(trim,set)choose/choosewhen, otherwiseforeach/foreachbind/
MyBatis 是如何将 sql 执行结果封装为目标对象并返回的都有哪些映射形式
答第一种是使用 resultMap 标签逐一定义列名和对象属性名之间的映射关系。第二种是使用 sql 列的别名功能将列别名书写为对象属性名比如 T_NAME AS NAME对象属性名一般是 name小写但是列名不区分大小写MyBatis 会忽略列名大小写智能找到与之对应对象属性名你甚至可以写成 T_NAME AS NaMeMyBatis 一样可以正常工作。
有了列名与属性名的映射关系后MyBatis 通过反射创建对象同时使用反射给对象的属性逐一赋值并返回那些找不到映射关系的属性是无法完成赋值的。 MyBatis 能执行一对一、一对多的关联查询吗都有哪些实现方式以及它们之间的区别
答能MyBatis 不仅可以执行一对一、一对多的关联查询还可以执行多对一多对多的关联查询多对一查询其实就是一对一查询只需要把 selectOne() 修改为 selectList() 即可多对多查询其实就是一对多查询只需要把 selectOne() 修改为 selectList() 即可。
关联对象查询有两种实现方式一种是单独发送一个 sql 去查询关联对象赋给主对象然后返回主对象。另一种是使用嵌套查询嵌套查询的含义为使用 join 查询一部分列是 A 对象的属性值另外一部分列是关联对象 B 的属性值好处是只发一个 sql 查询就可以把主对象和其关联对象查出来。
那么问题来了join 查询出来 100 条记录如何确定主对象是 5 个而不是 100 个其去重复的原理是 resultMap 标签内的 id 子标签指定了唯一确定一条记录的 id 列MyBatis 根据 id 列值来完成 100 条记录的去重复功能 id 可以有多个代表了联合主键的语意。
同样主对象的关联对象也是根据这个原理去重复的尽管一般情况下只有主对象会有重复记录关联对象一般不会重复。
举例下面 join 查询出来 6 条记录一、二列是 Teacher 对象列第三列为 Student 对象列MyBatis 去重复处理后结果为 1 个老师 6 个学生而不是 6 个老师 6 个学生。
t_idt_names_id1teacher381teacher391teacher401teacher411teacher421teacher43
MyBatis 是否支持延迟加载如果支持它的实现原理是什么
答MyBatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载association 指的就是一对一collection 指的就是一对多查询。在 MyBatis 配置文件中可以配置是否启用延迟加载 lazyLoadingEnabledtrue|false。
它的原理是使用 CGLIB 创建目标对象的代理对象当调用目标方法时进入拦截器方法比如调用 a.getB().getName() 拦截器 invoke() 方法发现 a.getB() 是 null 值那么就会单独发送事先保存好的查询关联 B 对象的 sql把 B 查询上来然后调用 a.setB(b)于是 a 的对象 b 属性就有值了接着完成 a.getB().getName() 方法的调用。这就是延迟加载的基本原理。
当然了不光是 MyBatis几乎所有的包括 Hibernate支持延迟加载的原理都是一样的。
MyBatis 的 xml 映射文件中不同的 xml 映射文件id 是否可以重复
答不同的 xml 映射文件如果配置了 namespace那么 id 可以重复如果没有配置 namespace那么 id 不能重复毕竟 namespace 不是必须的只是最佳实践而已。
原因就是 namespaceid 是作为 MapString, MappedStatement 的 key 使用的如果没有 namespace就剩下 id那么id 重复会导致数据互相覆盖。有了 namespace自然 id 就可以重复namespace 不同namespaceid 自然也就不同。
MyBatis 中如何执行批处理
答使用 BatchExecutor 完成批处理。
MyBatis 都有哪些 Executor 执行器它们之间的区别是什么
答MyBatis 有三种基本的 Executor 执行器
SimpleExecutor 每执行一次 update 或 select就开启一个 Statement 对象用完立刻关闭 Statement 对象。ReuseExecutor 执行 update 或 select以 sql 作为 key 查找 Statement 对象存在就使用不存在就创建用完后不关闭 Statement 对象而是放置于 MapString, Statement内供下一次使用。简言之就是重复使用 Statement 对象。BatchExecutor执行 update没有 selectJDBC 批处理不支持 select将所有 sql 都添加到批处理中addBatch()等待统一执行executeBatch()它缓存了多个 Statement 对象每个 Statement 对象都是 addBatch()完毕后等待逐一执行 executeBatch()批处理。与 JDBC 批处理相同。
作用范围Executor 的这些特点都严格限制在 SqlSession 生命周期范围内。
MyBatis 中如何指定使用哪一种 Executor 执行器
答在 MyBatis 配置文件中可以指定默认的 ExecutorType 执行器类型也可以手动给 DefaultSqlSessionFactory 的创建 SqlSession 的方法传递 ExecutorType 类型参数。
MyBatis 是否可以映射 Enum 枚举类
答MyBatis 可以映射枚举类不单可以映射枚举类MyBatis 可以映射任何对象到表的一列上。映射方式为自定义一个 TypeHandler 实现 TypeHandler 的 setParameter() 和 getResult() 接口方法。 TypeHandler 有两个作用
一是完成从 javaType 至 jdbcType 的转换二是完成 jdbcType 至 javaType 的转换体现为 setParameter() 和 getResult() 两个方法分别代表设置 sql 问号占位符参数和获取列查询结果。
MyBatis 映射文件中如果 A 标签通过 include 引用了 B 标签的内容请问B 标签能否定义在 A 标签的后面还是说必须定义在 A 标签的前面
答虽然 MyBatis 解析 xml 映射文件是按照顺序解析的但是被引用的 B 标签依然可以定义在任何地方MyBatis 都可以正确识别。
原理是MyBatis 解析 A 标签发现 A 标签引用了 B 标签但是 B 标签尚未解析到尚不存在此时MyBatis 会将 A 标签标记为未解析状态然后继续解析余下的标签包含 B 标签待所有标签解析完毕MyBatis 会重新解析那些被标记为未解析的标签此时再解析 A 标签时B 标签已经存在A 标签也就可以正常解析完成了。
简述 MyBatis 的 xml 映射文件和 MyBatis 内部数据结构之间的映射关系
答MyBatis 将所有 xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。在 xml 映射文件中 parameterMap 标签会被解析为 ParameterMap 对象其每个子元素会被解析为 ParameterMapping 对象。 resultMap 标签会被解析为 ResultMap 对象其每个子元素会被解析为 ResultMapping 对象。每一个 select、insert、update、delete 标签均会被解析为 MappedStatement 对象标签内的 sql 会被解析为 BoundSql 对象。
为什么说 MyBatis 是半自动 ORM 映射工具它与全自动的区别在哪里
答Hibernate 属于全自动 ORM 映射工具使用 Hibernate 查询关联对象或者关联集合对象时可以根据对象关系模型直接获取所以它是全自动的。而 MyBatis 在查询关联对象或关联集合对象时需要手动编写 sql 来完成所以称之为半自动 ORM 映射工具。