1.#{}和${}的区别是什么?【掌握】
考核点:
Mybatis占位符的使用。
答:
#{}是预编译处理,${}是字符串替换;
Mybatis在处理#{}时,会将SQL中的#{}替换为?,本质上是调用PreparedStatement实现执行命令;
Mybatis在处理${}时,就是把${}替换成变量的值,本质上是调用Statement实现执行命令;
使用#{}可以有效的防止SQL注入,提高系统安全性。
2.实体类属性与表中字段不匹配时,有哪些解决方案?【掌握】
考核点:ORM映射。
答:
第1种:通过在查询的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种:通过resultMap标签来映射字段名和实体类属性名的一一对应的关系:
<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>
3.模糊查询like语句该怎么写?【掌握】
考核点:模糊查询
答:
第1种:在Java代码中添加SQL通配符;
//Java代码中:
String wildcardname = ”%smi%”;
list<name> names = mapper.selectlike(wildcardname);
//Mapper映射文件中:
<select id=”selectlike”>
select name from foo where bar like #{value}
</select>
第2种:在SQL语句中拼接通配符(MYSQL):
//Java代码中:
String wildcardname = ”smi”;
List<name> names = mapper.selectlike(wildcardname);
//Mapper映射文件中:
<select id=”selectlike”>
select name from foo where bar like ‘%’ #{value} ‘%’
</select>
第3种:在SQL语句中使用Concat函数拼接通配符,支持所有数据库:
//Java代码中:
String wildcardname = ”smi”;
List<name> names = mapper.selectlike(wildcardname);
//Mapper映射文件中:
<select id=”selectlike”>
select * from foo where bar like concat("%",concat(#{value},"%"))
</select>
4.通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?【重点】
考核点:Mybatis工作原理
答:
Dao接口里的方法为什么不能重载:
Dao接口,就是人们常说的Mapper接口;
Mybatis启动后需要加载Mapper.xml映射文件,映射文件中每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象;
Mybatis会将MapperStatement对象以键值对的形式维护起来,MappedStatementId(采用Mapper映射文件的namespace+标签的ID组成)作为键,MapperStatement对象作为值;
调用接口中的方法时,通反射获取Mapper接口的完整限定名+方法名确定MappedStatementId,然后使用MappedStatementId定位一个MappedStatement对象;
所以,Dao接口里的方法,是不能重载的,因为Mybatis是使用MappedStatementId的寻找策略定位具体的MappedStatement对象,而MappedStatement对象就是实际调用的SQL语句;
Dao接口的工作原理:
Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象;
代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的SQL,然后将SQL执行结果返回。
5.Mybatis是如何将SQL执行结果封装为目标对象并返回的?都有哪些映射形式?【掌握】
考核点:Mybatis ORM映射。
答:
第一种是使用ResultMap标签,逐一定义数据库表的字段名和实体类的属性名之间的映射关系;
第二种是使用SQL语句为数据库表的字段定义别名功能,将字段别名设置为实体类的属性名;
设置了字段名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给实体类的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
6.如何执行批量插入?【掌握】
考核点:动态SQL与SQL语句。
答:
第一种:在Java代码中,循环执行指定SQL语句。效率低,不推荐。
首先,创建一个简单的insert语句:
<insert id=”insertname”>
insert into names (name) values (#{value})
</insert>
然后在Java代码中像下面这样执行批处理插入:
list<string> names = new arraylist();
names.add(“fred”);
names.add(“barney”);
sqlsession sqlsession = sqlsessionfactory.opensession(true);
try {
namemapper mapper = sqlsession.getmapper(namemapper.class);
for (string name : names) { mapper.insertname(name); }
sqlsession.commit();
} finally { sqlsession.close(); }
第二种:支持MYSQL版本
<insert id=”insertname”>
insert into names (name) values
<foreach collections="names" item="item" separator=","> (#{item}) </foreach>
</insert>
第三种:支持Oracle并支持序列
<insert id=”insertname”>
begin
<foreach collections="names" item="item" >
insert into names (name) values (#{item});
</foreach>
end;
</insert>
第四种:通用版本,但是不支持Oracle序列
<insert id=”insertname”>
insert into names (name,gender)
<foreach collections="names" item="item" separator="union">
select #{item.name} , #{item.gender}
</foreach>
</insert>
7.如何获取自动生成的主键值?【掌握】
考核点:获取插入后主键值。
答:
insert方法总是返回一个int值,这个值代表的是插入的行数,而自动生成的键值在insert方法执行完后可以被设置到传入的参数对象中。
自增列示例:
<!--
useGeneratedKeys="true":设置使用自增列的值
keyProperty="stuId":设置自增列的值存入到JavaBean的哪个属性
-->
<insert id="insert" useGeneratedKeys="true" keyProperty="stuId" parameterType="Student">
insert into student (stuName,age,gender,address) values (#{stuName},#{age},#{gender},#{address})
</insert>
序列示例:
<insert id="insert" parameterType="Student">
<selectKey order="BEFORE" resultType="integer" keyProperty="stuId" >
select seq.nextval from dual
</selectKey>
insert into student (stuId,stuName,age,gender,address)
values (seq.currval,#{stuName},#{age},#{gender},#{address})
</insert>
或
<insert id="insert" parameterType="Student">
<selectKey order="AFTER" resultType="integer" keyProperty="stuId" >
select seq.currval from dual
</selectKey>
insert into student (stuId,stuName,age,gender,address)
values (seq.nextval,#{stuName},#{age},#{gender},#{address})
</insert>