Mybatis 关联查询

MyBatis Collection小记—— 关联查询、递归查询、多字段关联     经常会用到mybatis的Collection标签来做级联查询或递归查询,现通过一个伪例来简单的说明一下使用中的关键点:    首先先列出三个表,给出一个场景:1,角色表t_role( id,name ) 2,菜单表t_menu( id, name, pid )菜单表是个有个pid,指向上级菜单的id,所以是个树形表3,角色菜单关联表t_role_menu( role_id, menu_i... 阅读详情

MyBatis魔法堂:即学即用篇

一、前言                                        

  本篇内容以理解MyBatis的基本用法和快速在项目中实践为目的,遵循Make it work,better and excellent原则。 技术栈为MyBatis3.2.7+log4j1.2.17+sqlite3+jdk1.7。

 

二、示例                               

  示例代码功能:

    学校人员管理系统,对象分别为学生、教师和班级,学生与班级为多对一关系,班级与教师为一对多关系。示例代码主要为操作学生对象。

  1. 表结构

  学生表(TStudentML)

字段数据类型备注
IDInteger主键
NameText姓名
ClassIDInteger班级ID

  班级表(TClassML)

字段数据类型备注
IDInteger主键
NameText姓名

  教师表(TTeacherML)

字段数据类型备注
IDInteger主键
NameText姓名
ClassIDInteger班级ID

 

  2. 项目目录结构

复制代码
  src
   |-- com
   |     |-- entity
   |     |       |-- ETeacher
   |     |       |-- EStudent
   |     |       |-- EClass
   |     |-- dao
   |             |-- studentMapper.xml
   |             |-- StudentMapper.java
   |             |-- DBase.java
   |             |-- DStudent.java
   |-- mybatis-config.xml
   |-- db.db
   |-- log4j.properties
   |-- config.properties
复制代码

  3. 数据库配置文件(config.properties)

driver=org.sqlite.JDBC
url=jdbc:sqlite:src/db.db

  4. log4j.properties

log4j.rootLogger=TRACE, studout
log4j.appender.studout=org.apache.log4j.ConsoleAppender
log4j.appender.studout.layout=org.apache.log4j.PatternLayout
log4j.appender.studout.layout.ConversionPattern=[%5p]%t -%m%n

  5. mybatis-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>
    <!--
      引入外部properties配置文件,后面内容则通过${属性名}来引用属性值
        在使用实例化SqlSessionFactory时,还可以通过new SqlSessionFactoryBuilder.build(config.xml的InputStream实例, Properties实例)来设置属性值。
    优先级从高到低是:
        1. 通过build方法入参设置
        2. 通过resource引入的属性
        3. 通过property标签设置的属性
    --> <properties resource="config.properties"></properties>
    <!--强制指定MyBatis使用log4j作为日志日志框架,若不指定那么当部署到如Tomcat等应用容器时,会被容器设置为使用common-logging来记录日志--> <settings> <setting name="logImpl" value="LOG4J"/> </settings>
    <!--设置自定义JAVA类型的别名,否则在映射文件中的resultType、parameterType等特性值就需要填写全限定类名才有效--> <typeAliases>
     <!--
      这时对于包下的类,在映射文件中的resultType、parameterType等特性值,我们只需写类名或首字母小写的类名
          当自定义JAVA类配合@Aliase("别名")使用时,只需写别名即可,且不区分大小写
      MyBatis对JAVA原生类型定义了内置别名:
        `int`,`long`等就是`_int`,`_long`
        `Integer`,`String`就是`int`,`string`
        --> <package name="com.entity"/> </typeAliases> <environments default="dev">
     <!--运行环境配置--> <environment id="dev">
       <!--
           type属性用于指定事务管理器类型
             JDBC:使用JDBC的提交和回滚设置,依赖从数据源获取的连接来管理事务范围。
             MANAGED:让容器(如Spring)来管理事务的生命周期。默认情况会关闭连接,
          若不想关闭连接则需要如下配置:
             <transactionManager type="MANAGED">
                  <property name="closeConnection" value="false"/>
                </transactionManager>
            --> <transactionManager type="JDBC"></transactionManager>
            <!--
           type属性用于指定连接池类型
              UNPOOLED:连接用完就关闭,不放到连接池
              POOLED:连接用完则放在连接池
          --> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <!--虽然sqlite不用填写username和password,但这两个节点必须保留,否则将报错--> <property name="username" value=""/> <property name="password" value=""/> </dataSource> </environment> </environments>
    <!--向MyBatis注册映射信息--> <mappers> <mapper resource="com/dao/studentMapper.xml"></mapper> </mappers> </configuration>
复制代码

  6. 实体类                            

复制代码
// 教师实体类
public class ETeacher{
  private int id;
  private String name;
  // 省略各种setter和getter.......
}

// 班级实体类
public class EClass{
  private int id;
  private String name;
  // 省略各种setter和getter.......
}

// 学生实体类
public class EStudent{
  private int id;
  private String name;
  private EClass myClass;
  private List<ETeacher> teachers;
  // 省略各种setter和getter.......
}
复制代码

  7. 映射接口

复制代码
public interface StudentMapper{
  /**
   * 通过姓名获取学生信息(不含教师、班级信息)
   * @param name 学生姓名
   * @return
   */
  EStudent getJustStudentInfo(String name);

  /**
   * 通过姓名模糊查询学生信息(不含教师、班级信息)
   * @param name 学生姓名
   * @return
   */
  List<EStudent> getJustStudentInfos(String name);

  /**
   * 通过姓名和班级名称获取学生信息(含教师、班级信息)
   * @param studentName 学生姓名
   * @param className 班级名称
   * @return
   */
  EStudent getStudentInfo(String studentName, String className);

  /**
   * 新增学生信息
   * @param student
   * @return
   */
  void addStudent(EStudent student);

  /**
   * 删除学生信息
   * @param id
   * @return
   */
  void delStudent(int id);
}
复制代码

  8. 映射文件

复制代码
<?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="main.dao.StudentMapper">
  <select id="getJustStudentInfo" resultType="EStudent">
      select ID,Name from TStudentML where Name = #{0}
  </select>

  <select id="getJustStudentInfos" resultType="EStudent">
      select * from TStudentML 
      <if test="#{0} != null">
          where name like '%'+#{0}+'%'
      </if>
  </select>

  <select id="getStudentInfo" resultMap="getStudentInfoResultMap">
      select 
          a.ID a_id, a.Name a_name, 
          b.ID b_id, b.Name b_name, 
          c.ID c_id, c.Name c_name, c.ClassID c_classId
      from 
      TStudentML a left outer join TClassML b on(a.ClassID=b.ID) left outer join TTeacherML c on(b.ID=c.ClassID) <trim prefix="where" prefixOverrides="and">   <if test="#{0} != null">   a.Name like '%'+#{0}+'%' </if> <if test="#{1} != null">   and b.Name like '%'+#{1}+'%' /if> </trim> </select> <resultMap id="getStudentInfoResultMap" type="EStudent"> <id property="id" column="a_id"/> <result property="name" column="a_name"/>
<!-- 一对一关系 --> <association property="myClass" javaType="EClass"> <id property="id" column="b_id"/> <result property="name" column="b_name"/> </association>
<!-- 一对多关系 --> <collection property="teachers" ofType="ETeacher"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <result property="classId" column="c_classId"/> </collection> </resultMap> <insert id="addStudent" parameterType="EStudent"> insert into TStudentML(Name, ClassID) values(#{name}, #{myClass.id}) </insert> <delete id="delStudent"> delete from TStudentML where ID = #{0} </delete> </mapper>
复制代码

  9. 数据库操作基类

复制代码
public class DBase{
  private static SqlSessionFactory factory = null;
  public DBase(){
    if (factory != null) return;

    InputStream is = this.getClass().getClassLoader().getResourceAsStream("mybatis-config.xml");
    factory = new SqlSessionFactoryBuilder().build(is);
  }
  
  /**
   * 获取SqlSession实例,使用后需调用实例的close()函数释放资源
   * @return
   */
  protected SqlSession openSession(){
    return factory.openSession();
  }
}
复制代码

  10. 数据库操作类

复制代码
public class DStudent extends DBase{
    /**
     * 通过姓名获取学生信息(不含教师、班级信息)
     * @param name 学生姓名
     * @return
     */
    public EStudent getJustStudentInfo(String name){
        EStudent ret = null;
        SqlSession session = openSession();
        try{
            StudentMapper sm = session.getMapper(StudentMapper.class);
            ret = sm.getJustStudentInfo(name);
        }
        finally{
            session.close();
        }

        return ret;
    }
    
    /**
     * 通过姓名模糊查询学生信息(不含教师、班级信息)
     * @param name 学生姓名
     * @return
     */
    public List<EStudent> getJustStudentInfos(String name){
        List<EStudent> ret = null;
        SqlSession session = openSession();
        try{
            StudentMapper sm = session.getMapper(StudentMapper.class);
            ret = sm.getJustStudentInfos(name);
        }
        finally{
            session.close();
        }

        return ret;
    }
    
    /**
     * 通过姓名和班级名称获取学生信息(含教师、班级信息)
     * @param name 学生姓名
     * @param className 班级名称
     * @return
     */
    public EStudent getStudentInfo(String name, String className){
        EStudent ret = null;
        SqlSession session = openSession();
        try{
            StudentMapper sm = session.getMapper(StudentMapper.class);
            ret = sm.getStudentInfo(name, className);
        }
        finally{
            session.close();
        }

        return ret;
    }

    /**
     * 新增学生信息
     * @param student
     */
    public void addStudent(EStudent student){
        SqlSession session = openSession();
        try{
            StudentMapper sm = session.getMapper(StudentMapper.class);
            sm.addStudent(student);
            session.commit();
        }
        finally{
            session.close();
        }
    }
    
    /**
     * 删除学生信息
     * @param id
     */
    public void delStudent(int id){
        SqlSession session = openSession();
        try{
            StudentMapper sm = session.getMapper(StudentMapper.class);
            sm.delStudent(id);
            session.commit();
        }
        finally{
            session.close();
        }
    }
}
复制代码

 

三、基础知识                          

  作为一个ORM框架,可以知道其至少由对象模型转换为关系模型、关系模型转换为对象模型和缓存管理这三个模块组成。

  MyBatis在对象模型转换为关系模型模块的实现方式是对象模型实例属性+自定义SQL语句,好处是对SQL语句的可操作性高,同时简化SQL入参的处理;坏处是对于简单的单表操作,依旧要写SQL语句,无法由对象模型自动生成SQL,最明显的问题是在开发初期数据表结构不稳定,一旦表结构改了,代码上不仅要改对象模型还要改SQL语句(不过MyBatis也考虑到这点,通过<sql>标签实现SQL语句复用,缓解这样问题)。

  关系模型转换为对象模型则采用关系模型结果集字段映射到对象模型实体字段的方式处理。

  缓存模块则分为SQL语句缓存和查询数据缓存两种,由于MyBatis需要开发者自定义SQL语句,因此SQL语句缓存不用考虑;而查询数据缓存则被分为一级和二级缓存,一级缓存以事务为作用域,二级缓存以同一个映射集为作用域,而且二级缓存采用直写的方式处理缓存数据被修改和删除的情况。

(本人不才,曾开发轻量级ORM框架LessSQL.Net,由于设计为SQL语句必须由对象模块实例映射生成,而关系模型数据集合无法自动填充任意的对象模型实体中,无法支撑复杂的查询语句,而缓存方面仅实现了SQL语句缓存性能优化有限,因此框架仅适用于小型工具软件。因为踩过这些坑,所以对ORM框架有一点浅薄的认识和看法)

   言归正转,我们一起了解MyBatis的基础知识吧。

   1. MyBatis框架配置文件

       实际上就是MyBatis会话工厂的配置文件,用于配置如缓存、日志框架、数据库链接信息、两种模型间转换的处理器和注册映射集等。通过上文大家应该知道如何Make it work了。而Make it better也是从这里出发。

   2. 映射集

       映射集是由多个“标识”——“SQL语句”组成,映射记录上还有如入参类型、返回类型等信息,为对象关系模型转换引擎提供元数据。

       设置映射集的方式有两种,一种是通过接口,一种通过xml文档。但上文示例采用两者相结合的方式,综合两者优点。

       [a]. 映射接口方式

复制代码
public interface StudentMapper{
  @Select("select * from TStudentML where Name=#{0}")
  EStudent getJustStudent(String name);

  @Insert("insert into TStudentML(Name, ClassID) values(#{name}, #{myClass.id})")
  void addStudent(EStudent student);
  
  @Delete("delete from TStudentML where ID=#{0}")
  void delStudent(int id);

  @Update("update TStudentML set Name=#{name},ClassID=#{myClass.id} where ID=#{id}")
  void updateStudent(EStudent student);
}
复制代码

       很明显通过接口方式定义映射集是无法实现上文中复杂的查询操作,而好处就是代码量锐减,且由于使用了接口,所以IDE的智能提示和编译时语法、依赖关系检查会降低编码错误的风险。

      使用接口方式需要将mybatis-config.xml中的mapper改为如下内容 

复制代码
<mappers>
    <mapper class="com.dao.StudentMapper"></mapper>
</mappers>
<!--
  或注册某包下的所有映射接口
  <mappers>
     <package name="com.dao"/>
  </mappers>
-->
复制代码

    [b]. 映射XML文件

       上文示例已经展示了映射XML文件的用法,下面我们逐个细节理解。

       1. select、update、delete和insert标签用于填写对应动作的SQL语句。

       2. parameterType属性就是入参类型具体法则如下(parameterMap已被deprecated,所以不理也罢):

          a. parameterType为POJO类型时,可通过 #{属性名} 填入属性值(该属性值经过防SQL注入处理),也可通过 ${name} 填入属性raw值(未经过防SQL注入处理的属性值),更爽的是 #{} 支持短路径操作如上文中的 #{myClass.id} 。

          b. parameterType为int、long等值类型时,当仅有一个入参时,可以使用 #{任意字符} 填入属性值,但无法通过 ${任意字符串} 填入属性raw值(报找不到改实例属性),还可以通过 #{0} 和 #{param0} 来填入属性值;而入参为多个时,则只能使用 #{0}到#{n} 和 #{param0}到#{paramn} 来填入属性值了;但由于动态SQL下的标签仅识别 #{0} 等格式的占位符,因此建议通过使用 #{0} 格式的占位符,保持代码一致性。

       3. resultType属性就是返回值类型。

       4. sql标签则用于重用SQL片段,示例如下:

复制代码
<sql id="studentCols">
  Name, ClassID
</sql>
<select id="qryStudent" resultType="EStudent">
  select <include id="studentCols"/> from TStudentML
</select>
复制代码

       5. 模糊查询

           网上有很多做法,但试过不是效果不好,就是报错,误打误撞发现最原始的做法 '%'+#{0}+'%'就OK了!

  6. 一对一关系

           一对一关系MyBatis为我们提供 嵌套结果、嵌套查询 两种查询方式。由于嵌套查询需要向数据库执行两次查询操作,因此推荐使用嵌套结果方式。

           嵌套结果示例:

复制代码
<!-- resultMap属性值为配置返回值映射信息的resultMap标签的id值 -->
<select id="getClass" parameterType="int" resultMap="ClassResultMap"> select * from class c inner join teacher t on(c.tid = t.id) where t.id = #{0} </select>
<!-- type属性值为返回值的JAVA数据类型 --> <resultMap id="ClassResultMap" type="Cls">
  <!--
  id标签表示对象属性对应的是表主键
   result标签表示对象属性对应的是普通表字段
注意:必须用id或result标出需要返回的字段/属性映射,否则在查询多条记录时,仅会返回最后一条记录
 --> <id property="id" column="c_id"/> <result property="name" column="c_name"/>
  <!--
    一对一关系采用association标签配置关联信息
    javaType为JAVA数据类型
  --> <association property="teacher" javaType="Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> </resultMap>
复制代码

          嵌套查询示例:

复制代码
<select id="getClass" parameterType="int" resultMap="ClassResultMap">
  select * from class where tid = #{id}
</select>
<select id="getTeacher" parameterType="int" resultType="Teacher">
  select t_id id, t_name name from teacher where t_id = #{0}
</select>
<resultMap id="ClassResultMap" type="Cls">
  <id property="id" column="c_id"/>
  <result property="name" column="c_name"/>
  <!--
    select属性值为第二执行SQL语句id
    而column属性值为传递给第二执行SQL语句的入参,而且入参为第一次SQL语句的查询结果集字段值
注意:若嵌套查询的条件不只一个,那么就需要将column属性设置为column="{prop1: fie;d1, prop2: field2}",然后嵌套查询的SQL中通过#{prop1},#{prop2}获取查询条件值
  --> <association prorperty="teacher" column="tid" select="getTeacher"> </association> </resultMap>
复制代码

       7. 一对多关系

    一对多关系同样分为 嵌套结果 和嵌套查询两种,由于嵌套查询会由于N+1次查询导致性能下降,一般推荐使用嵌套结果的做法,但有些查询操作必须使用嵌套查询才能完成。

              嵌套结果示例:

复制代码
<select id="getClass" parameterType="int" resultMap="ClassResultMap">
  select * from class c inner join student s on(c.id = s.cid) where c.id = #{id}
</select>
<resultMap id="ClassResultMap" type="Cls">
<!--
   注意:必须用id或result标出需要返回的字段/属性映射,否则在查询多条记录时,仅会返回最后一条记录
  -->
  <id property="id" column="c_id"/>
  <result property="name" column="c_name"/>
  <!--
    一对多关系采用collection标签来配置映射信息
    ofType属性值为返回值的JAVA数据类型
  --> <collection prorperty="students" ofType="Student"> <id property="id" column="s_id"/> <result property="name" column="s_name"/> </collection> </resultMap>
复制代码

          嵌套查询示例:

复制代码
<select id="getClass" parameterType="int" resultMap="ClassResultMap">
  select * from class where tid = #{id}
</select>
<select id="getStudents" parameterType="int" resultType="Student">
  select s_id id, s_name name from student where cid = #{id}
</select>
<resultMap id="ClassResultMap" type="Cls">
<!-- 注意:若不写这句,那么c_id字段将作为嵌套查询的条件,而不会赋值到id属性了 --> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <collection prorperty="students" column="c_id" select="getStudents"> </collection> </resultMap>
复制代码

       8. 动态SQL

           MyBatis的动态SQL与数据库中通过exec、sp_executesql()等执行的动态SQL目的是一致的,只是操作形式的不同而已。MyBatis的动态SQL定义方式上与文本模板定义无异,定义后均为经过类似于模板引擎的模块进行解析得到最终的数据。下面我们来了解具体的标签吧。

         [a]. <if test="逻辑条件判断"></if> 

             如果test内返回true,则标签体的内容将被添加到最终结果中。示例:

<if test="name != null and job != null">
and Name like '%'+#{name}+'%' and Description like '%'+#{job}+'%'
</if>

              注意:test语句中的逻辑条件判断必须使用入参的属性名或键名,而不能使用#{0}或#{1}等形式的入参,否则条件判断一律视为true。         

 

         [b]. <choose></choose> 

              相当于Java的switch语句。示例:

复制代码
<choose>
  <when test="#{title} !=null">
    and Title = #{title}
  </when>
  <when test="#{name} !=null">
    and Name = #{name}
  </when>
  <otherwise>
    and Age > 10
  </otherwise>
</choose>
复制代码

 

   [c]. <where></where> 

          用于处理动态条件时,where留存与否的尴尬。具体就是

复制代码
select * from tbl
where
<if test="#{name}!=null">
  Name = #{name}
</if>
<if test="#{title}!=null">
  and Title = #{title}
</if>
复制代码

               当两个条件都不符合时,sql语句就变成 select * from tbl where ,报错是必然的。而 where标签 会根据其标签体是否有值来决定是否插入where关键字,并会自动去除无用的 or 和 and 关键字。示例:

复制代码
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
复制代码

    

   [d]. <set></set> 

      用于在update语句中,动态设置更新的列。示例:

复制代码
<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>
复制代码

 

   [e].<trim></trim> 

                 当标签体有内容时则为内容添加前缀、后缀,而且可以除去内容前后部分内容。与 where标签 功能相同的示例:

复制代码
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
<!--
prefix属性值为添加到内容的前缀信息
prefixOverrides属性值为除去内容前的内容,当需要除去多个内容时,使用管道符|分割,注意:空格也将被除去
-->
<trim prefix="where" prefixOverrides="AND |OR "> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </trim> </select>
复制代码

       与 set标签 功能相同的示例:

复制代码
<update id="updateAuthorIfNecessary">
  update Author
    <trim prefix="set" suffixOverrides=",">
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </trim>
  where id=#{id}
</update>
复制代码

 

      [f]. <foreach></foreach> 

      主要用于IN关键字,示例:

复制代码
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>
复制代码

           入参为List或Array类型时,MyBatis会自动将其添加到内部Map对象中,并且List类型对象的键名为list,Array类型对象的键名为array,并通过 foreach标签 的collection属性指定入参的键名。而item属性用于指定 foreach标签 内集合元素的占位符名称,index属性则指定 foreach标签  内当前元素索引的占位符名称,而open、close和separator属性则分别指定动态SQL的开头、结束文本和集合元素项间的分隔符。

 

  3. 操作数据

      如上文示例那样,通过 SqlSessionFactoryBuilder实例 生成 SqlSessionFactory实例 ,然后在生成操作数据库的 SqlSession实例 。

      需要注意的是:

    a. 每次使用完 SqlSession实例 必须调用其 close() 方法释放链接;

              b. 由于mybatis-config.xml中 <transactionManager type="JDBC"></transactionManager> 而且通过 SqlSessionFactory实例.openSession() 获取链接对象,因此链接对象默认时不会自动提交增、删和改操作的,因此需要调用 commit() 方法手动提交操作。

  4. 生命周期

     [a]. SqlSessionFactoryBuilder

   由于`SqlSessionFactoryBuilder`实例用于生成`SqlSessionFactory`实例而已,因此并没有必要以应用程序全局作为作用域,并且无必要多线程共享。因此作为函数的局  部变量使用即可。

     [b]. SqlSessionFactory

    作为数据库连接池和连接池管理器使用,为达到数据库连接复用的效果,`SqlSessionFactory`实例应当以程序全局作为作用域,并且多线程共享。采用单例或静态单例模式较好

     [c]. SqlSession

   由于`SqlSession`实例非线程安全,因此作为函数的局部变量使用。而且由于数据库连接为共享资源,因此必须遵循晚调用早释放原则, 确保调用`close()`函数释放连接。

 

四、总结                            

     尊重原创来自:http://www.cnblogs.com/fsjohnhuang/p/4014819.html 

Mybatis关联查询【附实战案例】 Mybatis关联查询,一对一,一对多,多对多 阅读详情

相关推荐

rk3568 RGMII KSZ8795 MAC TO MAC

参考《Rockchip_Developer_Guide_Linux_MAC_TO_MAC_CN.pdf》

明天乌儿会歌唱 6490

Mybatis(三)各种查询功能

我们发现报的错误了,报的结果异常。我们在去调用Mapper接口中的方法的时候,我们在底层调用的是sqlSession里面一个具体的方法。我们当前方法的返回值为User,所以说我们当前调用的是selectOne方法。当我们当前方法的返回值为User的时候,我们修改映射文件,,将条件删除,变为搜索全部的数据,即返回为多条数据。以字段名为键,以字段的值为值。实体类和map集合的区别在于实体类里面他的属性是固定的,而map集合里面没有固定的键。我们发现我们查出来的结果有2条,但是我们当前返回的值是一个Map集合。

超级程序诞生的博客 2704

PySWMM新手避坑指南:从安装到批量处理INP文件的完整流程(附常见错误解决方案)

本文为PySWMM新手提供从环境搭建到批量处理INP文件的完整避坑指南。详细讲解了虚拟环境配置、库安装方法,并针对“无法打开输入文件”和对象访问错误等高频问题提供解决方案。核心部分展示了如何利用Python脚本实现INP文件的批量运行、结果汇总以及参数自动化修改,显著提升SWMM模型的工作效率。

weixin_29092031的博客 392

MyBatis魔法堂:即学即用篇

一、前言                                          本篇内容以理解MyBatis的基本用法和快速在项目中实践为目的,遵循Make it work,better and excellent原则。 技术栈为MyBatis3.2.7+log4j1.2.17+sqlite3+jdk1.7。   二、示例                            ...

weixin_33819479的博客 152

基于PI双闭环解耦控制的三相SVPWM电压型逆变器(3)--调制方法

阐述SPWM和SVPWM的原理以及实现方法

weixin_58670090的博客 6258

PyQtWebEngine安装避坑指南:快速解决ModuleNotFoundError

本文详细解析了PyQt5开发中常见的ModuleNotFoundError: No module named 'PyQt5.QtWebEngineWidgets'错误。核心原因是PyQt5 5.11版本后,网页引擎组件被独立为PyQtWebEngine包。文章对比了退回旧版本、独立安装及使用Conda等多种解决方案,并提供了针对Windows、macOS和Linux不同平台的实战安装指南与验证方法,帮助开发者快速解决依赖问题。

weixin_29056101的博客 425

Mybatis多表关联查询(一对多关联查询)

Mybatis多表关联查询(一对多关联查询)

qq_58258855的博客 1万+

AST实战:解密Akamai混淆JS代码的完整流程

本文详细解析了如何使用AST技术解密Akamai混淆的JS代码,包括定位关键代码、AST解混淆实战步骤及常见问题解决方案。通过实际案例演示了从混淆代码到清晰逻辑的完整处理流程,并提供了工具推荐和法律合规建议,帮助开发者有效应对反爬虫技术。

weixin_33725722的博客 313

Mybatis 查询时报 com.mysql.jdbc.Connection.isValid(I)Z错误的解决方法

Mybatis 查询时 报 com.mysql.jdbc.Connection.isValid(I)Z错误的解决方法

hzk1791318012的博客 847

ACS运动控制器编程 怎么学习

本文介绍了ACS运动控制器编程的完整学习路线,从零基础到实战应用。ACS是以色列高端多轴运动控制平台,适用于自动化设备、精密平台等项目。学习路径包括:1)安装官方软件SPiiPlusControlSuite;2)掌握轴、运动模式和指令三个核心概念;3)学习10个基础指令;4)编写首个运动程序;5)结合C#进行联合编程。进阶内容包括多轴同步、电子凸轮等工业应用,并推荐官方手册作为主要学习资源。通过7天的系统学习,即可掌握单轴运动控制,结合C#实现工业级设备开发。

StevenChen的博客 1306

YOLOv11涨点改进| CVPR 2026 |独家创新首发、特征融合改进篇| 引入FAAFusion傅里叶角对准融合模块,促进高低频特征融合,增强模型在小目标、密集目标检测和旋转目标检测任务高效涨点

🔥本文提出FAAFusion傅里叶角对准融合模块,用于改进YOLOv11网络模型。该模块通过在特征金字塔融合阶段对齐高低层特征的方向信息,缓解传统FPN直接融合带来的方向冲突问题。FAAFusion利用傅里叶旋转等变性原理,在频域估计主方向并进行特征对齐,显著提升了多尺度特征表达的一致性与有效性。实验表明,该方法在DOTA等遥感数据集上取得了新的最先进水平,特别适用于旋转目标检测任务。文章详细介绍了模块原理、结构优势,并提供了三种不同的YOLOv11改进配置方案和完整的核心代码实现。

Ai缝合怪、助力小伙伴高效发论文 150

Mybatis

Mybatis 1JDBC JDBC 的开发步骤 1、注册驱动:主要告诉 JVM 我们的程序将要使用哪一种数据库 2、获取连接:使用 JDBC 中的类,获得数据库的连接对象 Connection 3、获得语句执行平台:通过 Connection 可以获取执行者对象,Statement、PreparedStatement. 4、执行 SQL 语句:使用执行者对象,向数据库中执行 SQL 语句,然后可以得到对应的接口,有单个结果,也可能有结果集 ResultSet。 5、处理结果 6、释放对象:

qq_53943932的博客 3872

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

MyBatis之关联查询

在使用MyBatis进行数据库操作时,关联查询是一种重要的查询方式。它能够在一个查询中同时检索多个表中的数据,从而提高查询效率和性能。在开始学习和使用MyBatis的关联查询之前,我们需要先了解一些基础概念和知识,包括数据库表、实体类、Mapper接口和Mapper.xml文件等。在接下来的博客文章中,我们将逐步学习如何使用MyBatis进行关联查询,并通过示例代码演示如何实现多对一和一对多的关联查询。希望通过这些介绍,你能够掌握MyBatis关联查询的基本知识和技能,并能够在实际项目中应用这些知识。

liubopro666的博客 1889

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Mybatis之关联查询

Mybatis–关联查询 当查询内容涉及到具有关联关系的多个表时,就需要使用关联联查。根据表与表间的关联关系的不同,关联查询分为四种: 一对一关联查询 一对多关联查询 多对一关联查询 多对多关联查询 一、一对一关联查询 一对多关联查询是指,在查询一对象的时候,同时将其所关联的一个对象也都查询出来。 例:一张身份证卡只对应一个人 一个人只对应一张身份证 1.定义实体 Card: public class Card { private int cardId;

qq_33978195的博客 3702

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

MyBatis——MyBatis的关联查询

MyBatis的关联查询(一对一,一对多,多对多)

wan的博客 1237

Mybatis 的关联查询

关联查询 一、关联查询的分类 一对一关联查询 一对多关联查询 多对一关联查询 多对多关联查询 二、一对多关联查询 一对多关联查询是指,在查询一对象的时候,同时将其所关联的多放对象也都查询出来。 例:国家Country与部长Minister间的一对多关系 1.定义实体 若定义的是双向关联,即双方的属性中均有对方的对象作为作用域属性出现,那么它们在定义个各自的toString()方法时需要注意,只让某一方可以输出另一方即可,不要让双方的toString()方法均可输出对方。这样会形成递归调用,程序出错。 C

qq_40623824的博客 1014

mybatis 实现关联查询

比如user表和role表有关联关系,有这样一条语句:查询uesr的同时将user的某一列数据作为参数一并查询role表符合条件的数据,限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的。菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。订单与订单详情是一对多关系,订单详情与商品是一对一关系,反之商品与订单详情是一对多关系,订。场合:常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可。

m0_68274160的博客 1114

五,mybatis的多表关联查询

mybatis的多表关联查询

weixin_51637046的博客 2624

09【MyBatis多表关联查询】

表关系有如下几种一对多多对一(MyBatis就是一对一)一对一多对多(一对多+一对多)举例一:一对多:一个部门下有多个员工部门与员工的关系:一对多多对一:多个员工属于一个部门。员工与部门的关系:多对一单独拿出一个员工来说,他都只能属于一个部门。所以,在mybatis中把多对一看成了一对一。一个用户对应一个身份证号码。那么用户与身份证号码关系就是一对一多对多:一个老师教多个学生。老师与学生的关系:一对多一个学生有多个老师。学生与老师:一对多,这种双向一对多,就是多对多。 Emp实体类: Dept实体类: 3.

緑水長流*z 2182

MyBatis(二)——关联查询

Mybatis关联查询,做项目的时候,会经常用到。本文少了mybatis的一对一、一对多、多对多关联查询。

weixin_43691723的博客 2311

Mybatis关联查询

Mybatis关联查询 Mybatis可以执行关联查询,可以是一个sql语句也可以是多个sql语句,不管怎么样都会用到标签: &lt;association&gt;&lt;/association&gt; &lt;collection&gt;&lt;/collection&gt; 下面记录下单条SQL语句的写法。 涉及的实体类: MyTest1 mport lombok.Data; impo...

chuan_day的专栏 714

mybatis之关联查询

mybatis之关联查询一、简单一对一级联查询二、嵌套结果与嵌套查询三、练习①创表数据:②实体类的创建①Resource实体类:②Role实体类③RoleResource实体类④User实体类③mapper文件夹下面的UserMapper接口④resources下创建mapper文件夹,在mapper文件下创建userMapper.xml文件①userMapper.xml文件内容⑤创建配置文件:mybatis-conf.xml⑥Test类里面测试结果是否和预期的一样四、练习结果 一、简单一对一级联查询   

faramita_of_mine的博客 1634

【MyBatis学习笔记 六】MyBatis关联查询和集合查询

之前我们做的都是单表查询,那么问题来了,如果我们想要做多表关联查询该怎么处理呢,本篇Blog来探索关联查询(多对一关系)和集合查询(一对多关系)的实现方式。同样还是在之前的Person表基础上做一些扩展。 数据及代码准备 首先我们预设一个场景:一条人员Person数据对应多个账户BankAccount数据,然后分别进行账户数据的查询时获取到关联的人员数据【多对一关联查询】和通过人员获取账户数据【一对多关联查询】。 1 数据表准备 首先我们需要准备两张数据表,首先Person表是之前准备好的,我们还是用之前预

MaoLin Tian's Blog 4472

mybatis 关联查询

insert: parameterType 参数类型 :你传递的参数类型 ,如果有接口的话 就不用说清楚这个类型 selectKey: keyProperty 属性名称 keyColumn 列名 ...

weixin_34113237的博客 224
上一篇: MyBatis ResultMap详解
下一篇: Eureka与ZooKeeper 比较
shadow_zed
博客等级 码龄10年 6289粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值