Java Mybatis面试题解析(上)

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>

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值