#{}和${}区别
-
#{}
是预编译,mybatis处理#{}
时,会将它替换成?
,调用preparedStatement的set方法来赋值,使用#{}
能有效防止sql注入 -
${}
是字符串替换,mybatis使用${}
时会直接将其替换成字符串
实体类属性名和表字段名不一致
- 使用别名,在sql语句中使用
as
将表字段名和属性名关联
<select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>
select order_id as id, order_no as orderNo ,order_price as price form orders where order_id=#{id};
</select>
- 使用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>
like查询
- 在java代码使用通配符
- 在sql语句使用通配符
mybatis如何将执行sql的结果封装成目标对象并返回的,有哪些映射方式
第一种就是使用别名,第二种就是使用resultMap,有了字段名和属性名的映射关系之后,mybatis可以通过反射创建对象,通过反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
如何获取自动生成的(主)键值?
insert 方法总是返回一个int值 - 这个值代表的是插入的行数。
而自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。
如何在mapper中传递多个参数
- 使用占位符,用
#{0}
和#{1}
表示第一个和第二个参数 - 使用@param注解
- 使用Map集合作为参数装载
Mybatis的动态标签
- Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。
- Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind。
- 其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
通常一个xml文件会和一个DAO接口对应,DAO的原理,DAO接口里面的方法是否能重载
- DAO接口,又称为Mapper接口,接口的全限定名,又是映射文件的namespace,接口的方法名,就是映射文件中的MappedStatement,接口方法的参数就是传递给sql的参数
- Mapper接口是没有实现类的,当调用接口方法时,接口全限定名+方法名拼接字符串作为key值,可唯一定位一个mappedStatement
- Dao接口的方法是不能重载的,因为全限定名+方法名的保存和寻找策略
- 工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理将dao接口生产代理Proxy对象,代理对象会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回
myBatis是否支持延迟加载,原理是什么
- Mybatis支持association关联对象和collection关联集合对象的延迟加载,association指一对一,collection指一对多;通过配置lazyLoadingEnable=true/false
- 使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器发现a.getB()为null,就会单独发送事先先保存的查询关联B对象的sql,把B查询上来,使用a.setB(b),再使用a.getB().getName()
- Hibernate的延迟加载原理一致
Mybatis的Executor执行器
- simpleExecutor:每执行一次update和select,就开启一个Statement对象,用完立刻关闭
- reuseExecutor:执行update或select,以sql为key查找Statement对象,存在就使用,不存在就创建,用完之后不关闭,属于重复使用的Statement对象
- BatchExecutor:执行update,将所有的sql都添加到批处理中,等待统一执行,缓存了多个Statement对象,每个Statement对象都是addBatch完毕后,等待逐一执行executeBatch()批处理
- 都严格控制在session的生命周期内
Mybatis插件的原理以及实现
- Mybatis中仅可以编写ParameterHandler、ResultSetHandler、StatementHandler、Executor4种接口的插件
- 使用JDK的动态代理,为需要拦截的接口生成代理对象以实现方法拦截,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法
- 实现Mybatis的插件需要实现Interceptor接口的intercept()方法,然后给插件添加注解,指定需要拦截的哪一个接口的方法,然后在配置文件添加插件配置
Mybatis和hibernate区别
- Mybatis属于半自动ORM框架,需要自己编写sql,可以严格控制sql的执行性能,灵活度高,非常适合对关系数据要求不高的软件开发,例如互联网软件,企业运营类软件,但是mybatis无法做到数据库无关性,要实现多个数据库需要定义多套sql映射文件
- hibernate属于全自动ORM,数据库无关性好,对于关系模型要求高点软件,如果使用hibernate可以节省很多代码,提高效率,但是学习门槛高,在性能和对象模型之间权衡需要很强的经验和能力