1. 它是什么?
1.它是一个半ORM(对象关系映射)框架,内部封装了JDBC。 开发时
您只需要关注SQL语句本身,不需要花费精力加载驱动、创建连接、创建
等待复杂的过程。程序员直接编写原始SQL并可以严格控制SQL执行
有能力且高度灵活。
2. 可以使用XML或者注解来配置和映射原生信息,将POJO映射成数字。
数据库中的记录避免了几乎所有的 JDBC 代码以及手动设置参数和检索结果集。
3、通过xml文件或者注解配置要执行的各种功能,并通过
Java对象和SQL中的动态参数进行映射,生成最终执行的SQL语句。
然后框架执行sql并将结果映射到java对象中并返回它。 (从执行sql到返回
退货流程)。
2、优点:
1.基于SQL语句的编程相当灵活,不会对应用程序或数据库现有的设计产生任何影响。 SQL采用XML编写,将SQL与程序代码解耦,便于统一管理; 提供了 XML
标签支持编写动态SQL语句并且可以重复使用。
2、与JDBC相比,代码量减少50%以上,消除了JDBC中大量冗余代码。
需要手动开关连接;
3、对各种数据库的兼容性非常好(因为连接数据库都是使用JDBC,所以只要
支持 JDBC 支持的所有数据库)。
4、能够很好的融入;
5.提供映射标签,支持对象与数据库之间的ORM字段关系映射; 提供对象关系映射
标签支持对象关系组件维护。
3.框架的缺点:
1、编写SQL语句的工作量比较大,尤其是字段较多、关联表较多的情况下,开发人员编写起来非常困难。
对SQL语句的基础知识有一定要求。
2、SQL语句依赖于数据库,导致数据库可移植性差,无法随意更换数据库。
4、框架适用场合:
1、关注SQL本身,是一个足够灵活的DAO层解决方案。
2、对性能要求较高或者需求经常变化的项目,比如互联网项目,会
不错的选择。
5. 有什么区别?
1. 不一样
程序员自己写Sql语句。
2.直接编写原始SQL,可以严格控制SQL执行性能,灵活性高,非常
适合对关系数据模型要求不高的软件开发,因为这类软件的需求变化频繁。
寻求改变需要快速输出结果。 但灵活性的前提是不能实现数据库独立性。
如果需要实现支持多种数据库的软件,就需要定制多套SQL映射文件,工作量很大。
3、对象/关系映射能力强,数据库独立性好,对关系模型要求高
软件如果开发出来,可以节省大量代码,提高效率。
6.#{}和${}有什么区别?
#{}是预编译处理,
KaTeX 解析错误:'EOF',在 3: {}is̲ 字符串替换处得到 'is'。 ...{},将 ${} 替换为变量的值。
使用#{}可以有效防止SQL注入,提高系统安全性。
7、实体类中的属性名称与表中的字段名称不同怎么办?
类型一:通过在查询sql语句中定义字段名的别名,让字段名和实体类的别名
属性名称一致。
<select id=”selectorder” parametertype=”int” resultetype=”
me.gacl.domain.order”>
select order_id id, order_no orderno ,order_price price form
orders where order_id=#{id};
</select>
类型2:用于映射字段名和实体类属性名的一一对应关系。
<select id="getOrder" parameterType="int"
resultMap="orderresultmap">
select * from orders where order_id=#{id}
</select>
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
<!–用 id 属性来映射主键字段–>
<id property=”id” column=”order_id”>
<!–用 result 属性来映射非主键字段,property 为实体类属性名,column
为数据表中的属性–>
<result property = “orderno” column =”order_no”/>
<result property=”price” column=”order_price” />
</reslutMap>
8. 如何编写模糊查询like语句?
类型1:在Java代码中添加sql通配符。
string wildcardname = “%smi%”;
list<name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
select * from foo where bar like #{value}
</select>
类型2:在SQL语句中拼接通配符会导致SQL注入。
string wildcardname = “smi”;
list<name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
select * from foo where bar like "%"#{value}"%"
</select>
通常一个Xml映射文件都会有一个与之对应的Dao接口。 这个Dao接口是如何工作的呢? 如果Dao接口中的方法有不同的参数,该方法可以重载吗?
Dao接口是一个接口。 接口的完全限定名称是映射文件中的值;
接口的方法名就是映射文件中的id值; 这
参数是传递给sql的参数。
该接口没有实现类。 调用接口方法时,接口的全限定名+方法名用字符连接。
使用字符串作为键值来唯一定位one.in,每个
,,,标签都会被解析成
目的。
例如:com....,则只能
一旦找到,就com...以下id是
的。
接口中的方法不能重载,因为它们是使用完全限定名称+方法名称来保存和检索的。
寻找策略。 接口的工作原理是JDK动态代理,在运行时会使用JDK。
动态代理为接口生成一个代理对象proxy。 代理对象拦截接口方法并改为
执行代表的sql,然后返回sql执行结果。
10. 分页是如何进行的? 分页插件的原理是什么?
使用对象进行分页,分页是在结果集上执行的
存储页,不是物理页。可以直接在sql中写入带有物理分页的参数来完成物理分页。
寻呼功能,还可以使用寻呼插件完成物理寻呼。
分页插件的基本原理是利用提供的插件接口来实现自定义插件。
在拦截方法中拦截要执行的sql,然后重写sql,根据方言添加对应的对象
管理寻呼语句和物理寻呼参数。
11、如何将SQL执行结果封装成目标对象并返回?
第一种是使用标签来一一定义数据库列名和对象属性名之间的映射。
拍摄关系。
第二种方法是使用sql列别名功能,将列别名写为对象属性名。
有了列名和属性名的映射关系后,通过反射创建对象,并利用反射来
对象的属性一一赋值并返回。 对于那些找不到映射关系的属性,无法完成赋值。
12、如何批量插入?
首先,创建一个简单的语句:
<insert id=”insertname”>
insert into names (name) values (#{value})
</insert>
然后在java代码中执行批量插入,如下所示:
list < string > names = new arraylist();
names.add(“fred”);
names.add(“barney”);
names.add(“betty”);
names.add(“wilma”);
// 注意这里 executortype.batch
sqlsession sqlsession =
sqlsessionfactory.opensession(executortype.batch);
try {
namemapper mapper = sqlsession.getmapper(namemapper.class);
for (string name: names) {
mapper.insertname(name);
}
sqlsession.commit();
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
throw e;
}
finally {
sqlsession.close();
}
13、如何获取自动生成的(主)键值?
该方法始终返回一个 int 值,该值表示插入的行数。
如果采用自增策略,则该方法执行后可以将自动生成的键值设置为传入的键值。
在参数对象中。
<insert id=”insertname” usegeneratedkeys=”true” keyproperty=”
id”>
insert into names (name) values (#{name})
</insert>
name name = new name();
name.setname(“fred”);
int rows = mapper.insertname(name);
// 完成后,id 已经被设置到对象中
system.out.println(“rows inserted = ” + rows);
system.out.println(“generated key value = ” + name.getid());
14.如何传入多个参数?
1、第一种:
DAO层函数
public UserselectUser(String name,String area);
对应的 xml,#{0}代表接收的是 dao 层中的第一个参数,#{1}代表 dao 层中第二
参数,更多参数一致往后加即可。
<select id="selectUser"resultMap="BaseResultMap">
select * fromuser_user_t whereuser_name = #{0}
anduser_area=#{1}
</select>
2.第二种:使用@param注解:
public interface usermapper {
user selectuser(@param(“username”) string
username,@param(“hashedpassword”) string hashedpassword);
}
然后,就可以在 xml 像下面这样使用(推荐封装为一个 map,作为单个参数传递给
mapper):
<select id=”selectuser” resulttype=”user”>
select id, username, hashedpassword
from some_table
where username = #{username}
and hashedpassword = #{hashedpassword}
</select>
>3、第三种:多个参数封装成 map
```java
try {
//映射文件的命名空间.SQL 片段的 ID,就可以调用对应的映射文件中的
SQL
//由于我们的参数超过了两个,而方法中只有一个 Object 参数收集,因此
我们使用 Map 集合来装载我们的参数
Map < String, Object > map = new HashMap();
map.put("start", start);
map.put("end", end);
return sqlSession.selectList("StudentID.pagination", map);
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
throw e;
} finally {
MybatisUtil.closeSqlSession();
}
15.动态sql有什么用? 执行原理? 动态sql有哪些?
动态sql可以以标签的形式写在Xml映射文件中。 执行原理
它是根据表达式的值完成逻辑判断并动态拼接SQL的函数。
提供9个动态sql标签:trim | 哪里 | 集| | 如果|
| 当 | | 绑定。
16.除了常见的||updae| tag,Xml映射文件中还有哪些其他标签?
,,,,
,加上动态sql的9个标签,其中有sql片段标签,通过
标签引入sql片段,为不支持自增的主键生成策略标签。
符号。
Xml映射文件中,ID可以在不同的Xml映射文件中重复吗?
不同的Xml映射文件,如果配置的话,id可以重复; 如果没有配置
set,则id不能重复;
原因是+id是Map的key
用过,如果没有,就只剩下id了。 那么,重复的 id 就会导致数据互相覆盖。
同,自然id可以重复,不同,+id是自然
这不一样。
18.为什么叫半自动ORM映射工具? 它和全自动有什么区别?
它是一个全自动的 ORM 映射工具,使用查询相关对象或关联
收集对象时,可以根据对象关系模型直接获取,因此是全自动的。
。
和
查询相关对象或者相关集合对象时,需要手动编写sql来完成,所以称为半自动
主动 ORM 映射工具。
19. 一对一和一对多相关查询?
<mapper namespace="com.lcb.mapping.userMapper">
<!--association 一对一关联查询 -->
<select id="getClass" parameterType="int"
resultMap="ClassesResultMap">
select * from class c,teacher t where c.teacher_id=t.t_id and
c.c_id=#{id}
</select>
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
<!-- 实体类的字段名和数据表的字段名映射 -->
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher"
javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
</resultMap>
<!--collection 一对多关联查询 -->
<select id="getClass2" parameterType="int"
resultMap="ClassesResultMap2">
select * from class c,teacher t,student s where c.teacher_id=t.t_id
and c.c_id=s.class_id and c.c_id=#{id}
</select>
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher"
javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<collection property="student"
ofType="com.lcb.user.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
</mapper>
20. 实现一对一的方式有多少种? 具体是如何运作的呢?
有联合查询和嵌套查询。 联合查询是多个表的联合查询。 仅查询一次。 经过
里面的配置节点配置可以通过配置一对一的类来完成;
嵌套查询是先查一张表,然后根据这张表中结果的外键id去往另一张表。
查询数据也是通过配置,但是查询另一个表是通过属性配置。
21. 实现一对多有几种方法,它们是如何操作的?
有联合查询和嵌套查询。联合查询是几个表的联合查询。 仅查询一次。 经过
可以通过为里面的节点配置一对多的类来完成; 嵌套查询是先检查
一个表,根据这个表结果的外键id,去查询另一个表的数据也是通过
配置,但是另一个表的查询是通过节点配置的。
22.支持延迟加载吗? 如果支持,其实现原理是什么?
答:仅支持延迟添加关联对象和关联集合对象。
set指的是一对一查询,set指的是一对多查询。存在
在配置文件中可以配置是否启用延迟加载=true|false。
它的原理是利用CGLIB创建目标对象的代理对象。 当调用目标方法时,就会进入该块。
拦截器方法,比如调用a.getB().(),()方法发现a.getB()是
null 值,则将单独发送与 B 对象关联的预先保存的 SQL 查询,并上传 B 查询。
然后调用a.setB(b),这样a的对象b属性就有值了,然后完成a.getB().()
方法调用。 这就是延迟加载的基本原理。
当然不仅如此,几乎所有支持延迟加载的原理都包括
一样的。
23、一级、二级缓存:
1)一级缓存:基于本地缓存,其存储范围为
,在flush或者close之后,所有的缓存在
会被清除,并且默认开启一级缓存。
2)二级缓存与一级缓存机制相同,默认采用。
存储,不同的是它的存储范围是(),并且存储源可以自定义,
比如,二级缓存默认是不开启的。 要启用二级缓存,需要使用二级缓存属性类。
实现序列化接口(可用于保存对象的状态),可以在其映射文件中进行配置
;
3)对于缓存数据更新机制,当一定范围(一级缓存/二级缓存)
),默认情况下该范围内的所有缓存都会
被清除。
24.什么是接口绑定? 实施方法有哪些?
接口绑定就是在接口中任意定义一个接口,然后将接口中的方法绑定到SQL语句上。
确定我们可以直接调用接口方法了。 这样,与原来提供的方法相比,我们可以
拥有更灵活的选择和设置。
有两种方法可以实现接口绑定。 一种是通过注解绑定,也就是添加
@、@等注解包含用于绑定的Sql语句; 另一种是通过xml
在里面写SQL进行绑定。 此时,您需要在xml映射文件中指定所需的内容。
是接口的全路径名。当SQL语句比较简单时,使用注解绑定。 当SQL语句比较复杂时,使用注解绑定。
有时,xml用于绑定。 一般情况下,使用xml进行绑定的情况比较多。
25、调用所使用的接口有什么要求?
1、接口方法名与.xml中定义的每个sql的id相同;
2、.xml中定义的接口方法的入参类型和各sql
同一类型;
3、接口方法的输出参数类型以及.xml中定义的各个sql
同一类型;
4. .xml文件中的是接口的类路径。
27、简述插件的工作原理以及如何编写插件。
你只能写给,,
,这四个接口的插件使用JDK的动态代码
处理,为需要拦截的接口生成代理对象,实现接口方法拦截功能,每当执行这4种类型时
接口对象的方法,就会进入拦截方法,具体是()
当然,方法只会拦截您指定拦截的那些方法。