(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
(1)Mybatis 和 Hibernate 不同,它不完全是一个 ORM 框架,因为 MyBatis 需要程序员自己编写 Sql 语句。Mybatis 可以通过 XML 或注解方式灵活配置要运行的sql语句,并将 Java 对象和 sql 语句映射生成最终执行的 sql,最后将 sql 执行的结果再映射生成 Java 对象。
(2)Mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
(3)Hibernate对象/关系映射能力强,数据库无关性好。
#{}
(1)表示一个占位符号,通过#{}可以实现 preparedStatement 向占位符中设置值
(2)自动进行java类型和jdbc类型转换
(3)#{}可以有效防止sql注入
(4)如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
$ {}
(1)$ {}表示拼接sql串,通过 $ {}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换
(2)$ {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,$ {}括号中只能是value。
<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>
<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>
string wildcardname = “%smi%”;
list<name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
select * from foo where bar like #{value}
</select>
string wildcardname = “smi”;
list<name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
select * from foo where bar like "%"${value}"%"
</select>
第一种是使用 标签,逐一定义数据库列名和对象属性名之间的映射关系。
第二种是使用 sql 列的别名功能,将别名书写为对象属性名。
有了列明和属性名的映射关系之后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性是无法完成赋值的。
首先创建一个简单的 insert 语句:
<insert id = "insertname">
insert into names (name) value (#{value})
</insert>
然后在 Java 代码中这样执行批量插入:
list<string> names = new arraylist();
names.add(“fred”);
names.add(“barney”);
names.add(“betty”);
names.add(“wilma”);
sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);
namemapper mapper = sqlsession.getmapper(namemapper.class);
for (string name : names) {
mapper.insertname(name);
insrt 方法总是返回一个 int 值,这个值代表的是插入的行数。
如果采用自增长策略,自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。
<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());
第一种:
//Dao 层的函数
public User selectUser(String name, String area);
//对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。
<select id = "selectUser" resultMap = "BaseResultMap">
select * fromuser_user_t where user_name = #{0} and user_area=#{1}
</select>
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
Mybatis 动态 sql 可以在 xml 映射文件内,以标签的形式编写动态的 sql。执行原理是根据表达式的值完成逻辑判断并动态拼接 sql。
Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
、、、、,加上动态sql的9个标签,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。
Hibernate 属于全自动的 ORM 映射工具, 使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
Mybatis缓存
缓存的重要性是不言而喻的。 使用缓存, 我们可以避免频繁的与数据库进行交互, 尤其是在查询越多、缓存命中率越高的情况下, 使用缓存对性能的提高更明显。
mybatis 也提供了对缓存的支持, 分为一级缓存和二级缓存。 但是在默认的情况下, 只开启一级缓存(一级缓存是对同一个 SqlSession 而言的)。
同一个 SqlSession 对象, 在参数和 SQL 完全一样的情况先, 只执行一次 SQL 语句(如果缓存没有过期)。
在日志和输出中:
第一次查询发送了 SQL 语句, 后返回了结果;
第二次查询没有发送 SQL 语句, 直接从内存中获取了结果。
而且两次结果输入一致, 同时断言两个对象相同也通过。
总结: