相比jdbc mybatis在操作数据库方面比jdbc节省了大量的代码,及大量的代码冗余.使得操作起来更加简洁.
在Mapper中分别有着 select,insert, update,delete的这四个标签分别对应着SQL语句中的查询映射,添加映射,修改映射,删除映射.
<select id=""></select> <insert id=""></insert> <update id=""></update> <delete id=""></delete>
不同点
可以看到除了标签,SQL语句的作用不一致,以及除了select返回的数据不是受影响行数之外,其它的都是返回受影响行数,也就是返回的是int类型数据
相同点
都需要传入参数
xml代码如下
<select id="getProvider" resultType="Provider"> SELECT * FROM smbms_bill b JOIN smbms_provider p ON b.providerId=p.id WHERE b.providerId=#{id} </select> <update id="updatePwd" parameterType="User"> UPDATE `smbms_user` SET `userPassword` = #{userPassword} WHERE `id` = #{id} ; </update> <delete id="delUserById" parameterType="Integer"> delete from smbms_user where id=#{id} </delete> <insert id="add" parameterType="User"> INSERT INTO `smbms_user` (`userCode`, `userName`, `userPassword`, `gender`, `birthday`, `phone`, `address`, `userRole`, `createdBy`, `creationDate`, `modifyBy`, `modifyDate`) VALUES(#{userCode},#{userName},#{userPassword},#{gender}, #{birthday},#{phone},#{address},#{userRole},#{createdBy},#{creationDate}, #{modifyBy}, #{modifyDate}); </insert>
接口代码
List<Provider> getProvider(Integer id); int add(User u); int updatePwd(User u); int delUserById(int id);
测试类代码
public static void main(String[] args) { SqlSession sqlSession=null; List<Bill> bList = new ArrayList<>(); List<Provider> providers = new ArrayList<>(); try { sqlSession=MyBatisUtil.createSqlSession(); providers=sqlSession.getMapper(ProviderMapper.class).getProvider(1);for (Provider p : providers) { for (Bill b : p.getBills()) { System.out.println(b.getProductName()); } } } catch (Exception e) { e.printStackTrace(); logger.debug(e); }finally { MyBatisUtil.closeSqlSession(sqlSession); } } @org.junit.Test public void testAdd() { logger.debug("testAdd-----"); SqlSession sqlSession =null; int count=0; try { sqlSession = MyBatisUtil.createSqlSession(); User u = new User("测试用户", 1); u.setUserCode("test001"); u.setUserPassword("123456"); u.setBirthday(Date.valueOf("1999-09-09")); u.setAddress("测试地址"); u.setGenfer(1); u.setPhone("19973535706"); u.setCreatedBy(1); u.setCreationDate(Date.valueOf("1999-09-09")); count = sqlSession.getMapper(UserMapper.class).add(u); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); }finally { MyBatisUtil.closeSqlSession(sqlSession); } logger.debug("testAdd:"+count); } @org.junit.Test public void testModifyPwd() { logger.debug("testModifyPwd-----"); SqlSession sqlSession =null; int count=0; try { sqlSession = MyBatisUtil.createSqlSession(); User u = new User("测试用户修改", 1); u.setUserPassword("123456"); u.setId(15); count = sqlSession.getMapper(UserMapper.class).updatePwd(u); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); }finally { MyBatisUtil.closeSqlSession(sqlSession); } logger.debug("testModifyPwd:"+count); } @org.junit.Test public void testdel() { logger.debug("testdel-----"); SqlSession sqlSession =null; int count=0; try { sqlSession = MyBatisUtil.createSqlSession();; count = sqlSession.getMapper(UserMapper.class).delUserById(16); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); }finally { MyBatisUtil.closeSqlSession(sqlSession); } logger.debug("testdel:"+count); }
以上一个都传入了参数的,那么我们在来看共同点相同属性也就是parameterType,指的是传入的参数,一种具体的数据类型比如,int,String,自定义的对象等等
注意:传入的参数与SQL语句中参数名两者名称需一致,如果是自定义对象则需与对象中自定义的属性名称一致
此外还有一个属性parameterMap:参数有多个值,并且这多个值之间没有具体的联系,就可以考虑使用parameterMap,或者@param注解
那么再看select中的另外一个属性:resultType指的是返回的数据类型,而除了select其他的都没有,这是因为它们默认就是返回int因此不需要 resultType.
resultMap:必须要自己在这个xml中重新配置一个新的resultMap标签,
注意:当受影响行数为0时返回的值就会是null,因此返回值最好设置成integer而不是int
@Param注解实现多参数
List<Bill> getBill(@Param("id") Integer billId);
使用注解@Parma来传入多个参数,入@Param("id") Integer billId,相当于将该参数重命名为id,在映射的SQL中需要使用#{注解名}
<select id="getBill" parameterType="Integer" resultMap="billResult"> SELECT * FROM smbms_bill b JOIN smbms_provider p ON b.providerId=p.id WHERE b.providerId=#{id} </select>
resultType和resultMap的关联
在mybatis进行查询映射的时候,其实查询处理的每个字段值都放在一个对应的Map里面,其中关键是字段名,值则是对应的值,当select提供的返回类型属性
是在resultType的时候,My把提升会将Map里面的键值取出赋值给resultType所知道的对象对应的属性(即钓鱼对应的对象里的属性的setter方法进行填充).因此
,当resulttype的时候,直接在后台就能接收到其相应的值.其实mybatis的每个查询映射的返回类型都是resultMap,只是mybatis自动转换成了我们需要的类型
注意:resultType属性和resultMap属性不能同时存在,只能二者选其一
resultMap自定义映射
<resultMap type="Bill" id="billResult"> <result property="productName" column="productName"/> <result property="productDesc" column="productDesc"/> </resultMap> <select id="getBill" parameterType="Integer" resultMap="billResult"> SELECT * FROM smbms_bill b JOIN smbms_provider p ON b.providerId=p.id WHERE b.providerId=#{id} </select>
resultMap的属性值和子节点
- id属性:唯一标识符,此id值用于select于是resultMap的属性引用
- type:表示该resultMap的映射结果类型
- result节点:用于表示一些简单属性,其中column属性表示从数据库中查询的字段名,property则表示查询处来的字段对应的值赋给实体对象的那个属性
设置映射级别
<settings> <!-- 设置自动匹配所有属性 包括collection与association--> <setting name="autoMappingBehavior" value="FULL"/> </settings>
- NONE:禁止自动匹配
- PARTIAL(默认):自动匹配所以属性,内部嵌套的(association,collection)除外
- FULL:匹配所有
有了最高映射级别,因此自定义对象中的属性只要数据库中的字段相对应就不需要使用使用resultMap进行手动映射结果了
association
association:映射到Javabean的某个"复杂类型"属性,比如Javabean类,即Javabean内部嵌套一个复杂数据类型(Javabean)属性,这种情况就属性复杂类型的关联.
如类类,需要注意:association仅处理一对一的关联关系
实体类
private int id; /** * 编码 */ private String billCode; /** * 名称 */ private String productName; /** * 商品描述 */ private String productDesc; /** * 商品单位 */ private String productUnit; /** * 商品数量 */ private int productCount; /** * 商品总额 */ private int totalPrice; /** * 是否支付 1 未支付 0 已支付 */ private int isPayment; /** * 创建者 */ private String createdBy; /** * 创建时间 */ private Date creationDate; /** * 更新者 */ private String modifyBy; /** * 更新时间 */ private Date modifyDate; /** * 供应商id */ private int providerId; /** * 供应商 */ private Provider provider; // 省略getset方法
SQL映射
<resultMap type="Bill" id="billResult"> <result property="productName" column="productName"/> <result property="productDesc" column="productDesc"/> <association property="provider" resultMap="providerresult"></association> </resultMap> <resultMap type="Provider" id="providerresult"> <result property="proAddress" column="proAddress"/> <result property="proName" column="proName"/> </resultMap> <select id="getBill" parameterType="Integer" resultMap="billResult"> SELECT * FROM smbms_bill b JOIN smbms_provider p ON b.providerId=p.id WHERE b.providerId=#{id}
</select>
上面只选了部分属性进行映射
association属性
- property:映射数据库列的实体对象属性,此处为在Bill定义的属性:Provider
- result:property 映射数据库列的实体对象的属性,此处为Provider,column数控列名或别名
collection
作用与association非常类似,只不过collection对应的是类型中的集合
<resultMap type="Bill" id="billResult"> <result property="productName" column="productName"/> <result property="productDesc" column="productDesc"/> </resultMap> <resultMap type="Provider" id="providerresult"> <result property="proAddress" column="proAddress"/> <result property="proName" column="proName"/> <collection property="bills" ofType="Bill" resultMap="billResult"></collection> </resultMap> <select id="getProvider" resultMap="providerresult" parameterType="Integer"> SELECT * FROM smbms_bill b JOIN smbms_provider p ON b.providerId=p.id WHERE b.providerId=#{id} </select>
collection属性
- ofType:映射数据库列的实体对象属性,此处为在Bill定义的属性:Provider
- result:property 映射数据库列的实体对象的属性,此处为Provider,column数控列名或别名
resultType