平时我们都用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"> <!-- id表示这条SQL语句的标识,想执行这条语句,直接在Java中将他做作为参数即可,parameterType表示执行这条语句的时候需要传入一个Category类的对象 --> <insert id="addCategory" parameterType="Category" > insert into category_ ( name ) values (#{name}) </insert> <!-- 同上 --> <delete id="deleteCategory" parameterType="Category" > delete from category_ where id= #{id} </delete> <!-- id 和 parameterType 同上,其中 _int 对应的就是java中的int类型, int对应的是 java中的 Integer类型 注意:如果传进来的参数是基本类型那么#{}中的变量名字可以是任意的!!!!, resultType表示 执行这条语句的输出结果是一个 Category 类型的就是返回值类型--> <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"> <!-- 配置第一层 表格和javabean中的属性的对应 其中uid是user表中id的别称,这个在下面的SQL语句中配置了,因为user表和order表都有id,用别名来区分 colum是表中的列名,property是javabean中的成员变量的名字--> <id column="uid" property="id" /> <result column="username" property="username" /> <result column="sex" property="sex" /> <result column="address" property="address" /> <!-- 一对多的关系 用来配置第二层的 表格列名和第二层javabean的成员变量的对应关系--> <!-- property: 指的是装 第二层数据的成员变量的名字, ofType:指的是集合中元素的类型 --> <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"> <!-- 配置第一层,即第一张表 表格和javabean中的属性的对应 其中uid是user表中id的别称,这个在下面的SQL语句中配置了,因为user表和order表都有id,用别名来区分 colum是表中的列名,property是javabean中的成员变量的名字 现在开始配置User类的前几个成员变量--> <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" /> <!-- 上面配置的是User类的前几个成员变量,下一个成员变量ordersList是一个List,类型是Order,要用collection标签,collection标签中配置的就是Order这个bean与order表中的字段的的对应关系--> <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" /> <!--上面配置的是Order类中的前几个成员变量,orderdetails这个成员变量是List(是一对多的关系,即一个Order有多个OrderDetail),类型是OrderDetail,所以用collection标签,collection标签中配置的就是OrderDetail这个bean与表格的对应关系--> <collection property="orderdetails" ofType="OrderDetail"> <id column="odid" property="id" /> <result column="items_num" property="itemsNum" /> <result column="express" property="express" /> <!--上面配置的是OrderDetail类的前几个成员变量,下一个成员变量是Items类的对象items,由于items只是一个对象,所以用association标签,其中配置的就是Items类和最后一层表的字段的对应关系--> <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 不执行,就相当于直接查询全部。
<?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> </select> </mapper>
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>
<where>标签会进行自动判断
如果任何条件都不成立,那么就在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可以有两个层次,即类中的成员变量可以用来存放结果,同时,还可以用一个类的对象作为成员变量,来存放下一个层次的查询结果,比较适合用在一对多查询。
一对一查询,两种方法都可以用