终于把论文写得差很少了,系统也不急着完成,能够抽出点时间来完成这个系列的博客了。在写本博客以前我是惊慌失措的,高级映射一向是持久层框架里的重中之重,小到本身开发小系统,大到企业级开发,表的存在历来就不独立的。复杂交错的表之间的联系有时的确让后台开发人员头疼,而做为一个框架,要作的事就是把这种复杂程度降到最低。既然如此,咱们就赶快进入正文吧。java
先说一对一吧,前几篇博文里用到了User类,今天咱们再加上一个Orders订单类spring
一个订单只能由一个用户建立,因此根据订单查找用户是一对一的查找,因此当我想查出订单关联用户的全部记录怎么查呢?sql
咱们知道这个查询时不用输入参数的,因此在select里面是不用输入parameterType的,由此可知查询关键就在resultType了,的确,可是今天resultType有时会不够用,固然这都是后话了,在一对一查询里面resultType彻底是够用的,因此先看看这个怎么用吧数据库
先分析一波,咱们以前的全部的输出都有相会映射成相应的类,而咱们如今没有一个既包含User属性又包含Orders的类怎么办呢?mybatis
没错,就是新建一个知足以上条件的类,在这里有一个小技巧,咱们大多时候不须要关联表里的全部属性,好比在这里咱们只要user类的用户名和地址两个属性时,能够建立一个Orders类的扩展类,在该扩展类里添加属性username和address,就像下面app
解决了映射类,接下来就是xml文件了框架
先把sql语句贴上来测试
SELECT orders.*, user.username, user.address FROM orders, user WHERE orders.user_id = user.id;
这个sql语句很简单我就很少说了,有了这个mapper.xml就简单了ui
<select id="findOrderCustom" resultType="com.mybatis.pojo.OrderCustom"> SELECT orders.*, user.username, user.address FROM orders, user WHERE orders.user_id = user.id; </select>
而后就是遵循规范把mapper接口中的方法写了spa
//查询Orders关联User使用resultType public List<OrderCustom> findOrderCustom();
最后是测试代码
public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { //获得配置文件流 InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); //建立会话会话工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindOrderCustom() throws Exception { //建立会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //建立mapper代理对象 UserMapper userMapper= sqlSession.getMapper(UserMapper.class); List<OrderCustom> list=userMapper.findOrderCustom(); //调用代理对象的方法,打印结果 System.out.println(list.size()); sqlSession.close(); } }
大功告成,这个测试代码我已经测试过了没有问题,因此若是有跟初学者想拿着博主的代码运行一遍也是没有问题的。
其实从最开始学到如今,博主一直有一个疑问,为了实现映射一直以来表和类中属性的命名都要保持一致。可是咱们的java类规范命名都是用驼峰命名法,而数据库中属性命名大多采用下划线,这样保持一致不得不改变一方的命名规则,有没有什么方法能够两全呢?
答案就是resultMap,跟resultType直接进行类的映射不一样,resultMap讲究的是属性的映射。为了举例我再引进一个类,商品类Goods
表结构是这样的
接下来要作的事就是使用resultMap从表中查出全部的数据
在使用resultMap以前要先定义它,怎么定义呢,看代码
<!-- 定义resultMap --> <resultMap type="com.mybatis.pojo.Goods" id="goodsResultMap"> <id column="id" property="id"/> <result column="goods_name" property="goodsName"/> <result column="goods_price" property="goodsPrice"/> </resultMap>
主键用的是id,普通属性统一使用result。其中column和property分别表明在表和类中的属性名。resultMap的id是为了让下面的select语句引用的,接下来就给出select语句
<!-- 用resultMap查询goods信息 --> <select id="findGoodsResultMap" resultMap="goodsResultMap"> select * from goods </select>
整个xml的工做就算完成了,老规矩,下面给出mapper接口中的方法和测试代码(注意全部的测试都要加上@before的内容,我这里就懒得再写了)
//查询goods使用resultMap public List<Goods> findGoodsResultMap();
//测试查询goods使用resultMap @Test public void testFindGoodsResultMap() throws Exception { //建立会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //建立mapper代理对象 UserMapper userMapper= sqlSession.getMapper(UserMapper.class); List<Goods> list=userMapper.findGoodsResultMap(); //调用代理对象的方法,打印结果 System.out.println(list.size()); sqlSession.close(); }
写到这里,是否是有人想叫博主用resultMap的方法来写一写以前一对一的查询呢,放心吧,我后面也会讲到的。
首先看需求,若是我想列出全部用户的全部订单,可是用户信息又不能重复该怎么办,这个时候resultType就不够用了,由于需求是用户信息不能重复因此订单类要以list的方式存在
用户类中以下所示
而咱们的user表可否直接与上面的类对应呢,显然是不行的,既然不行的话resultMap就要上场了,以前就说过resultMap是细化到属性的对应的,咱们彻底能够将User类中的list中的对象细化到单独对应orders表,这样问题就解决了啊,那resultMap要怎么定义呢
首先把除去list的属性映射完(懒得麻烦就只写了id,username,address三个属性),写完就是下面这个样子
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> </resultMap>
千万要记住咱们的主表是user表,因此这里的type是User类
在resultMap里有一个属性collection,这个属性是专门为list准备的,让咱们来看看加上这个会是什么样子的
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> <collection property="orderList" ofType="com.mybatis.pojo.Orders"> <id column="id" property="id"/> <result column="user_id" property="user_id"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> </collection> </resultMap>
在collection中的property对应类中的属性名,ofType对应类中的list中的对象类型,在这里就是Orders类了,剩下的东西就和以前的配置彻底同样了,无非是将orders类中的属性名和表中的属性名对应了。
接下来就是select语句了
<!-- 查询用户关联订单使用resultMap --> <select id="findUserAndOrdersResultMap" resultMap="userAndOrdersResultMap"> SELECT user.id, user.username, user.address, orders.* FROM orders, user WHERE user.id = orders.user_id; </select>
是否是sql语句发现和以前写的好像是同样的,啊哈哈,我也是写完才发现的,需求是随便编的。。。
下面是mapper接口中的方法和测试代码(注意全部的测试都要加上@before的内容,我这里就懒得再写了)
//查询User关联Orders使用resultMap public List<User> findUserAndOrdersResultMap();
//测试查询User关联Orders使用resultMap @Test public void testFindUserAndOrdersResultMap() throws Exception { //建立会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //建立mapper代理对象 UserMapper userMapper= sqlSession.getMapper(UserMapper.class); List<User> list=userMapper.findUserAndOrdersResultMap(); //调用代理对象的方法,打印结果 System.out.println(list.size()); sqlSession.close(); }
个人数据库orders表中有三条记录,两条是同一个用户建立的,因此输出结果应该是2,没问题
最后啰嗦一点
若是需求变成订单再关联商品信息该怎么写呢,咱们知道订单和商品也是一对一的,即一个订单里面只能有一个该商品的记录(注意,这里的一个指的不是一件,若是用户买了多件该商品最后也会变成一个商品记录,变的只是数量而已),至关于在Orders类中增长一个Goods类做为属性,这个时候该怎么写呢,Mybatis提供了一个叫作association的属性用于关联类,至关于在collection里加上一个association,这个时候,xml文件会变成这样
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> <collection property="orderList" ofType="com.mybatis.pojo.Orders"> <id column="id" property="id"/> <result column="user_id" property="user_id"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/>
<association property="goods" javaType="com.mybatis.pojo.Goods"> <id column="id" property="id"/> <result column="goods_name" property="goodsName"/> <result column="goods_price" property="goodsPrice"/> </association>
</collection> </resultMap>
这个博主就不去测试了,反正套路都是同样的
有了association,以前那个订单关联用户的查询也就迎刃而解了,只需在Orders类中加一个用户类的属性紧接着配一个association就OK了。
终于写完了,我长舒了一口气,花了大半个下午的时间呢,后面还会写多对多查询,整合spring框架的内容等等。。。
最后最后说一点,这些知识我也是在短时间内学完的,算是现学现卖,若是哪位大神“随意”看了一眼发现了错误或者有更好的看法还请不吝赐教啊