平时我们都用JDBC访问数据库,除了需要自己写SQL之外,还必须操作Connection, Statment, ResultSet 这些其实只是手段的辅助类。 不仅如此,访问不同的表,还会写很多雷同的代码,显得繁琐和枯燥。
那么用了Mybatis之后,只需要自己提供SQL语句,其他的工作,诸如建立连接,Statement, JDBC相关异常处理等等都交给Mybatis去做了,那些重复性的工作Mybatis也给做掉了,我们只需要关注在增删改查等操作层面上,而把技术细节都封装在了我们看不见的地方。
Mybatis的配置文件有两个,第一个为主配置文件
主配置文件:
xml version="1.0" encoding="UTF-8" ?> DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="com.how2java.pojo"/> typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="1234"/> dataSource> environment> environments> <mappers> <mapper resource="com/how2java/pojo/Category.xml"/> mappers> configuration>
详细的每个标签的含义:
http://www.mybatis.org/mybatis-3/zh/configuration.html
第二个配置文件:
下面是简单的CRUD查询这样配置,也就是从一个表格中直接查询需要的数据,只关系到一个表格,比较简单
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.how2java.pojo"> <insert id="addCategory" parameterType="Category" > insert into category_ ( name ) values (#{name}) insert> <delete id="deleteCategory" parameterType="Category" > delete from category_ where id= #{id} delete> <select id="getCategory" parameterType="_int" resultType="Category"> select * from category_ where id= #{id} select> <update id="updateCategory" parameterType="Category" > update category_ set name=#{name} where id=#{id} update> <select id="listCategory" resultType="Category"> select * from category_ select> mapper>
下面这些是从多个表格中查询,即一个主表中的数据,然后在关联一些表格中的数据,可以分为一对一查询,就是主表中的一条记录,和关联的表格中的记录对应。一对多查询,主表中的一条记录和关联的表格中的多条记录对应。多对多,就是主表对关联表是一对多,同时,关联表对主表也是一对多,这就形成了两个表的多对多。多对一,查询的主表中的多条记录对应关联表的一条记录。
一对一配置
可以放在resultType中,也可以放在resultMap中(具体见收藏的文章)
一对多配置
一对多用resultMap来存放
存放查询结果的容器有两层组成,第一层是查询的主表的元素,第二层是关联的表格的元素,主表的元素直接在第一层的javabean中存放,第二层的元素放在后加进来的对象中,也就是association标签中配置的bean。
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mybatis.entity"> <resultMap type="User" id="userBean"> <id column="uid" property="id" /> <result column="username" property="username" /> <result column="sex" property="sex" /> <result column="address" property="address" /> <collection property="ordersList" ofType="Orders"> <id column="pid" property="id" /> <result column="user_id" property="userid" /> <result column="number" property="number" /> <result column="createtime" property="createTime" /> collection> resultMap> <select id="userAndOrder" resultMap="userBean"> select u.*, o.* , u.id 'uid' , o.id 'oid' from t_user u left join orders o on u.id = o.user_id select> mapper>
多对一配置
多对一的配置是用的association标签,用来映射一个对象,collection标签是用来映射List,多个对象组成的List,也就是一对多的情况,多对多就是综合了这两种情况。
多对多配置
多对多就是主表中的一条记录对应后面表格的多个记录,而后面表的每一条记录又对应多个记录,所谓的多对多。
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mybatis.entity"> <resultMap type="User" id="userBean"> <id column="uid" property="id" /> <result column="username" property="username" /> <result column="sex" property="sex" /> <result column="address" property="address" /> <result column="birthday" property="birthday" /> <collection property="ordersList" ofType="Orders"> <id column="oid" property="id" /> <result column="user_id" property="userid" /> <result column="number" property="number" /> <result column="createtime" property="createTime" /> <collection property="orderdetails" ofType="OrderDetail"> <id column="odid" property="id" /> <result column="items_num" property="itemsNum" /> <result column="express" property="express" /> <association property="items" javaType="Items"> <id column="iid" property="id" /> <result column="itemsname" property="itemsName" /> <result column="price" property="price" /> <result column="producetime" property="produceTime" /> <result column="detail" property="detail" /> association> collection> collection> resultMap> <select id="userAndOrderAndOrderDetailAndItems" resultMap="userBean"> select u.*, o.* , od.*, i.*, u.id 'uid' , o.id 'oid' , od.id 'odid' from t_user u left join orders o on u.id = o.user_id left join orderdetail od on od.orders_id = o.id left join items i on i.id = od.items_id select> mapper>
关于关系的建立
任意两个表,可以通过外键来产生关系,如果是一对多的关系,还可以用一个中间表来连接两个表格,中间表中的记录就是关系存在的依据,如果想建立两个表的关系,就需要在中间表中添加一条记录,记录添加之前,这两个表就是存在的,只是没有关系,分别获取两个表中的某一个字段,放在中间表中,就建立了一个关系。
关系的删除也是类似的,删除的只是关系,只是中间表的记录,并不影响原来的两个表格。
动态SQL
if标签
如果Product的字段比较多的话,为了应付各个字段的查询,那么就需要写多条sql语句,这样就变得难以维护。这个时候,就可以使用Mybatis 动态SQL里的if标签
这个标签是Mybatis中的内容,并不是 SQL语言中的。
直接看xml文件:
如果name有值,那就按照name进行模糊查询,不然 if 中的 where 不执行,就相当于直接查询全部。
"1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">namespace="com.how2java.pojo"> <select id="listProduct" resultType="Product"> select * from product_ <if test="name!=null"> where name like concat('%',#{name},'%') if> select>
where标签
如果要进行多条件判断,就会写成这样:
<select id="listProduct" resultType="Product"> select * from product_ <if test="name!=null"> where name like concat('%',#{name},'%') if> <if test="price!=0"> and price > #{price} if> select>
这么写的问题是:当没有name参数,却有price参数的时候,执行的sql语句就会是:
select * from product_ and price > 10.
这样执行就会报错,SQL语法错误。这个时候就需要Mybatis的where标签。
添加where标签
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.how2java.pojo"> <select id="listProduct" resultType="Product"> select * from product_ <if test="name!=null"> where name like concat('%',#{name},'%') if> <if test="price!=0"> and price > #{price} if> select> mapper>
如果任何条件都不成立,那么就在sql语句里就不会出现where关键字
如果有任何条件成立,会自动去掉多出来的 and 或者 or。
set标签
与 where标签 类似的,在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.how2java.pojo"> <select id="listProduct" resultType="Product"> select * from product_ <where> <if test="name!=null"> and name like concat('%',#{name},'%') if> <if test="price!=null and price!=0"> and price > #{price} if> where> select> <update id="updateProduct" parameterType="Product" > update product_ <set> <if test="name != null">name=#{name},if> <if test="price != null">price=#{price}if> set> where id=#{id} update> mapper>
trim标签
trim 用来定制想要的功能,比如where标签就可以用
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... trim>
来替换
set标签就可以用
<trim prefix="SET" suffixOverrides=","> ... trim>
来替换
运行 set标签 中的代码,其效果是一样的。
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.how2java.pojo"> <select id="listProduct" resultType="Product"> select * from product_ <trim prefix="WHERE" prefixOverrides="AND |OR "> <if test="name!=null"> and name like concat('%',#{name},'%') if> <if test="price!=null and price!=0"> and price > #{price} if> trim> select> <update id="updateProduct" parameterType="Product" > update product_ <trim prefix="SET" suffixOverrides=","> <if test="name != null">name=#{name},if> <if test="price != null">price=#{price}if> trim> where id=#{id} update> mapper>
when otherwise标签
作用和if else一样
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.how2java.pojo"> <select id="listProduct" resultType="Product"> SELECT * FROM product_ <where> <choose> <when test="name != null"> and name like concat('%',#{name},'%') when> <when test="price !=null and price != 0"> and price > #{price} when> <otherwise> and id >1 otherwise> choose> where> select> mapper>
foreach标签
这个语句的运行结果就相当于一个字符串,直接看例子
xml version="1.0" encoding="UTF-8"?> DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.how2java.pojo"> <select id="listProduct" resultType="Product"> SELECT * FROM product_ WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} foreach> select> mapper>
各个参数含义:
item表示集合中每一个元素进行迭代时的别名。
index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置。
open表示这个字符串的开头。
separator表示这个字符串的间隔符。
close就是结尾标识。
foreach标签的结果就相当于一个字符串: ( a , b , c)
abc就是调用这条语句时输入的List中的值,就是遍历元素,如果输入的参数是一个名为ids的List,ids中的元素为 1,3,5 那这个字符串就是 ( 1 , 2 , 3),那这条SQL语句就是
SELECT * FROM product_
WHERE ID in ( 1, 2, 3)
SQL语句的含义是:选择ID为1,2 ,3 的输出
bind标签
相当于给一个常用的字符串取别名而已,在需要用这个字符串的地方,直接用别名替代即可。
拿到一个表,先找主键,主键唯一,再找外键,外键就是对应到要关联的表上,
配置过程就建立Javabean与表格的对应关系,建立好对应关系,执行SQL语句之后,结果存放在结果集中,具体的查询逻辑,还是SQL完成
查询的结果集有两个存放的结构,resultType和resultMap,resultType只有一个层次,所查询出来的结果放在一个类中,resultMap可以有两个层次,即类中的成员变量可以用来存放结果,同时,还可以用一个类的对象作为成员变量,来存放下一个层次的查询结果,比较适合用在一对多查询。
一对一查询,两种方法都可以用