zoukankan      html  css  js  c++  java
  • mybatis实战教程(mybatis in action)之四:实现关联数据的查询

    有了前面几章的基础,对一些简单的应用是可以处理的,但在实际项目中,经常是关联表的查询,比如最常见到的多对一,一对多等。这些查询是如何处理的呢,这一讲就讲这个问题。我们首先创建一个Article 这个表,并初始化数据.

    复制代码
    Drop TABLE IF EXISTS `article`;
    Create TABLE `article` (
      `id` int(11) NOT NULL auto_increment,
      `userid` int(11) NOT NULL,
      `title` varchar(100) NOT NULL,
      `content` text NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- 添加几条测试数据
    -- ----------------------------
    Insert INTO `article` VALUES ('1', '1', 'test_title', 'test_content');
    Insert INTO `article` VALUES ('2', '1', 'test_title_2', 'test_content_2');
    Insert INTO `article` VALUES ('3', '1', 'test_title_3', 'test_content_3');
    Insert INTO `article` VALUES ('4', '1', 'test_title_4', 'test_content_4');
    复制代码

    你应该发现了,这几个文章对应的userid都是1,所以需要用户表user里面有id=1的数据。可以修改成满足自己条件的数据.按照orm的规则,表已经创建了,那么肯定需要一个对象与之对应,所以我们增加一个 Article 的class

    复制代码
    package com.yihaomen.mybatis.model;
    
    public class Article {
        
        private int id;
        private User user;
        private String title;
        private String content;
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public String getContent() {
            return content;
        }
        public void setContent(String content) {
            this.content = content;
        }
    
    }
    复制代码

    注意一下,文章的用户是怎么定义的,是直接定义的一个User对象。而不是int类型。

    多对一的实现
    场景:在读取某个用户发表的所有文章。当然还是需要在User.xml 里面配置 select 语句, 但重点是这个 select 的resultMap 对应什么样的数据呢。这是重点,这里要引入 association 看定义如下:

    复制代码
    <!-- User 联合文章进行查询 方法之一的配置 (多对一的方式)  -->    
        <resultMap id="resultUserArticleList" type="Article">
            <id property="id" column="aid" />
            <result property="title" column="title" />
            <result property="content" column="content" />
            
            <association property="user" javaType="User">
                <id property="id" column="id" />
                <result property="userName" column="userName" />
                <result property="userAddress" column="userAddress" />            
            </association>        
        </resultMap>
    
    <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
           select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article 
                  where user.id=article.userid and user.id=#{id}
        </select>
    复制代码

    这样配置之后,就可以了,将select 语句与resultMap 对应的映射结合起来看,就明白了。用association 来得到关联的用户,这是多对一的情况,因为所有的文章都是同一个用户的。

    还有另外一种处理方式,可以复用我们前面已经定义好的 resultMap ,前面我们定义过一个 resultListUser ,看这第二种方法如何实现:

    复制代码
    <resultMap type="User" id="resultListUser">
            <id column="id" property="id" />
            <result column="userName" property="userName" />
            <result column="userAge" property="userAge" />
            <result column="userAddress" property="userAddress" />
        </resultMap>
    
        <!-- User 联合文章进行查询 方法之二的配置 (多对一的方式) -->    
        <resultMap id="resultUserArticleList-2" type="Article">
            <id property="id" column="aid" />
            <result property="title" column="title" />
            <result property="content" column="content" />        
            <association property="user" javaType="User" resultMap="resultListUser" />             
        </resultMap>
        
        <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
           select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article 
                  where user.id=article.userid and user.id=#{id}
        </select>
    复制代码

    将 association  中对应的映射独立抽取出来,可以达到复用的目的。

    好了,现在在Test 类中写测试代码:

    复制代码
    public void getUserArticles(int userid){
            SqlSession session = sqlSessionFactory.openSession();
            try {
                IUserOperation userOperation=session.getMapper(IUserOperation.class);           
                List<Article> articles = userOperation.getUserArticles(userid);
                for(Article article:articles){
                    System.out.println(article.getTitle()+":"+article.getContent()+
                            ":作者是:"+article.getUser().getUserName()+":地址:"+
                             article.getUser().getUserAddress());
                }
            } finally {
                session.close();
            }
        }
    复制代码

    漏掉了一点,我们一定要在 IUserOperation 接口中,加入 select 对应的id 名称相同的方法:
    public List<Article> getUserArticles(int id);

    另外需要 Configuration.xml中加入

    <typeAliases>
    <typeAlias alias="User" type="com.shanheyongmu.mybatis.model.User"/>
    <typeAlias alias="Article" type="com.shanheyongmu.mybatis.model.Article"/>
    </typeAliases>

    然后运行就可以测试。 

     关联查询(多表查询)的时候。。设置的aid是作用吗?

    如果你不设置那个别名,那么结果集中将会有两个id列。会造成映射混乱吧。我做这个例子的时候没有设置别名,结果明明是4条记录,查询出来就只有1条了。

    由于原文转载还是存在错误。特此粘贴 run as main 通过的代码

    user.xml 如下

    复制代码
    <?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.shanheyongmu.mybatis.models.UserMapper"> -->
    <mapper namespace="com.shanheyongmu.mybatis.inter.IUserOperation">
       <select id="selectUserByID" parameterType="int" resultType="User">
         select * from user where id=#{id}
       </select>
        <!-- 多对一   方二 start--><!-- 为了返回list 类型而定义的returnMap -->
       <resultMap type="User" id="resultListUser">
         <id column="id" property="id"/>
         <result column="userName" property="userName"/>
         <result column="userAge" property="userAge"/>
         <result column="userAddress" property="userAddress"/>
       </resultMap>
       
       <!-- 返回list的select语句,注意resultMap的值是指向 前面定义好的-->
       <select id="selectUsers" parameterType="string" resultMap="resultListUser">
       select * from user where username like #{username}
       </select>
       <!-- User联合文章进行查询 方法二的配置 多对一 -->
       <resultMap type="Article" id="resultUserArticleList2">
       <id property="id" column="aid"/>
       <result property="title" column="title"/>
       <result property="content" column="content"/>
       <association property="user" javaType="User" resultMap="resultListUser"/>
       </resultMap>
       
      
        <!-- 多对一   方二 end-->
    <!-- User 联合文章进行查询 方法之一的配置 (多对一的方式)  start -->    
       <resultMap type="Article" id="resultUserArticleList">
          <id column="aid" property="id"/>
          <result column="title" property="title"/>
          <result column="content" property="content"/>
          
          <association property="user" javaType="User">
            <id column="id" property="id"/>
            <result column="userName" property="userName"/>
            <result column="userAddress" property="userAddress"/>
          </association>
       </resultMap>
          <!-- 方法一 end -->
          <!-- 查询语句 方法一 二公用 -->
       <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
       select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{id}
       </select>
    
    
       
       <!-- 执行增加操作的SQL语句。id和parameterType  
           分别与IUserOperation接口中的addUser方法的名字和  
           参数类型一致。以#{name}的形式引用Student参数  
           的name属性,MyBatis将使用反射读取Student参数  
           的此属性。#{name}中name大小写敏感。引用其他  
           的gender等属性与此一致。seGeneratedKeys设置  
           为"true"表明要MyBatis获取由数据库自动生成的主  
           键;keyProperty="id"指定把获取到的主键值注入  
           到Student的id属性 -->
           
         <insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        
           insert into user(userName,userAge,userAddress) values(#{username},#{userAge},#{userAddress})
         </insert>
         
         <update id="updateUser" parameterType="User">
         update user set userName=#{userName},userAge=#{userAge},userAddress=#{userAddress} where id=#{id}
         </update>
         
         <delete id="deleteUser" parameterType="int">
           delete from user where id=#{id}
         </delete>
         
         
       
    </mapper>
    复制代码

    Test.java

    复制代码
    package com.yihaomen.test;
    
    import java.io.Reader;
    import java.util.List;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import com.yihaomen.mybatis.inter.IUserOperation;
    import com.yihaomen.mybatis.model.Article;
    import com.yihaomen.mybatis.model.User;
    
    public class Test {
        private static SqlSessionFactory sqlSessionFactory;
        private static Reader reader; 
    
        static{
            try{
                reader    = Resources.getResourceAsReader("Configuration.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    
        public static SqlSessionFactory getSession(){
            return sqlSessionFactory;
        }
        
        public void getUserArticles(int userid){
            SqlSession session = sqlSessionFactory.openSession();
            try {
                IUserOperation userOperation=session.getMapper(IUserOperation.class);           
                List<Article> articles = userOperation.getUserArticles(userid);
                for(Article article:articles){
                    System.out.println(article.getTitle()+":"+article.getContent()+
                            ":作者是:"+article.getUser().getUserName()+":地址:"+
                             article.getUser().getUserAddress());
                }
            } finally {
                session.close();
            }
        }
        
        public static void main(String[] args) {
            Test testUser=new Test();
            testUser.getUserArticles(1);
        }    
      
    }
    复制代码

    config.xml如下

    复制代码
    <?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>
        <typeAlias alias="User" type="com.shanheyongmu.mybatis.model.User"/>
        <typeAlias alias="Article" type="com.shanheyongmu.mybatis.model.Article"/>
      </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/mybatis"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
          </dataSource>
        </environment>
      </environments>
      
      <mappers>
         <mapper resource="com/shanheyongmu/mybatis/model/User.xml"/>
      </mappers>
    
    
    </configuration>
    复制代码
  • 相关阅读:
    DotNetCore + Sonar + Coverlet 代码覆盖率检查
    Docker + Sonarqube 环境搭建
    使用cmd进行tfs的签入
    Swashbuckle.AspNetCore(v2.5.0)使用小记
    Ocelot(v7.0.6)使用小记
    layui.formSelects.render(); 需要先执行
    .net core编译时设置不自动生成“netcoreapp3.0”目录
    C# List引用类型的克隆
    HTTP Error 502.5
    GPS服务端(上)-Socket服务端(golang)
  • 原文地址:https://www.cnblogs.com/zwy890301/p/5935152.html
Copyright © 2011-2022 走看看