草庐IT

【MyBatis】自定义映射resultMap

热爱编程的小白白 2023-04-09 原文

目录

1.使用全局配置处理字段名和属性名不一致的情况

2.resultMap处理字段和属性的映射关系

1.处理一对一映射

2.多对一映射处理

级联方式处理映射关系

使用association处理映射关系

分步查询

3.一对多映射处理

1.collection

2.分步查询


前期准备:

 建立 t_emp 表,并添加数据:

 建立 t_dept 表,并添加数据:

实体类:Emp

package com.atguigu.mybatis.pojo;

public class Emp {
    private Integer empId;
    private String empName;
    private Integer age;
    private String gender;
    private Dept dept;

    public Emp() {
    }

    public Emp(Integer empId, String empName, Integer age, String gender, Dept dept) {
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
        this.dept = dept;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}

实体类:Dept

package com.atguigu.mybatis.pojo;

public class Dept {
    private Integer deptId;
    private String deptName;

    public Dept() {
    }

    public Dept(Integer deptId, String deptName) {
        this.deptId = deptId;
        this.deptName = deptName;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                '}';
    }
}

  接口:

public interface EmpMapper {
    Emp getEmpById(@Param("empId") Integer empId);
}

SQL:

select * from t_emp where emp_id = #{empId};

测试:

   public void test(){
        SqlSessionUtils sqlSessionUtils = new SqlSessionUtils();
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp empById = mapper.getEmpById(1);
        System.out.println(empById.toString());

    }

运行结果:

原因:JAVA中属性名 与 数据库中字段名不一致

1.使用全局配置处理字段名和属性名不一致的情况

若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性
名符合Java的规则(使用驼峰)
此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系:
1.可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
select emp_id empId,emp_name empName,age,gender from t_emp where emp_id = #{empId};

2.可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可
以在查询表中数据时,自动将_类型的字段名转换为驼峰
  <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为
userName

2.resultMap处理字段和属性的映射关系

1.处理一对一映射

<resultMap id="empResultMap" type="Emp">
    <id property="empId" column="emp_id"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="gender" column="gender"></result>
</resultMap>

    <select id="getEmpById" resultMap="empResultMap">
        select * from t_emp where emp_id = #{empId};
    </select>
resultMap:设置自定义映射
  • 属性:
  • id:表示自定义映射的唯一标识
  • type:查询的数据要映射的实体类的类型
  • 子标签:
  • id:设置主键的映射关系
  • result:设置普通字段的映射关系
  • association :设置多对一的映射关系
  • collection:设置一对多的映射关系
  • 属性:
  • property:设置映射关系中实体类中的属性名
  • column:设置映射关系中表中的字段名

2.多对一映射处理

级联方式处理映射关系

  <resultMap id="empAndDeptResultMap" type="Emp">
            <id column="emp_id" property="empId"></id>
            <result column="emp_name" property="empName"></result>
            <result column="age" property="age"></result>
            <result column="gender" property="gender"></result>

            <!--部门中的字段dept_id与Emp实体类中的属性dept中的deptId相对应 -->
            <!--部门中的字段dept_name与Emp实体类中的属性dept中的deptName相对应 -->
            <result column="dept_id" property="dept.deptId"></result>
            <result column="dept_name" property="dept.deptName"></result>
 </resultMap>



    <select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
      SELECT t_emp.*,t_dept.* FROM t_emp
      LEFT JOIN t_dept
      ON t_emp.dept_id=t_dept.dept_id
      where t_emp.emp_id=#{empId}
    </select>

接口:

Emp getEmpAndDeptById(@Param("empId") Integer empId);

测试:

    public void test2(){
        SqlSessionUtils sqlSessionUtils = new SqlSessionUtils();
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp empAndDeptById = mapper.getEmpAndDeptById(1);
        System.out.println(empAndDeptById);
        
    }

使用association处理映射关系

  <resultMap id="empAndDeptResultMap" type="Emp">
            <id column="emp_id" property="empId"></id>
            <result column="emp_name" property="empName"></result>
            <result column="age" property="age"></result>
            <result column="gender" property="gender"></result>
      <association property="dept" javaType="Dept">
          <id column="dept_id" property="deptId"></id>
          <result column="dept_name" property="deptName"></result>
      </association>

 </resultMap>

分步查询

①查询员工信息

    Emp getEmpAndDeptByStep(@Param("empId") Integer empId);
    <resultMap id="empAndDeptByStepResultMap" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <association property="dept"
                     select="com.atguigu.mybatis.mapper.DeptMapper.getDeptByStep" column="dept_id">
        </association>

    </resultMap>

    <select id="getEmpAndDeptByStep" resultMap="empAndDeptByStepResultMap">
     select * from t_emp where emp_id=#{empId};
    </select>
select:设置分步查询,查询某个属性的值的sql的标识(namespace.sqlid)
column:将sql以及查询结果中的某个字段设置为分步查询的条件
②根据员工所对应的部门 id 查询部门信息
    Dept getDeptByStep(@Param("deptId") Integer deptId);
    <select id="getDeptByStep" resultType="com.atguigu.mybatis.pojo.Dept">
        select * from t_dept where dept_id=#{deptId};
    </select>

测试:

    public void test3(){
        SqlSessionUtils sqlSessionUtils = new SqlSessionUtils();
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp empAndDeptByStep = mapper.getEmpAndDeptByStep(1);
        System.out.println(empAndDeptByStep);

    }

分步查询的优点:可以实现延迟加载
但是必须在核心配置文件中设置全局配置信息:
  • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
  • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的 sql
此时可通   association和 collection 中的   fetchType 属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加载)   |  eager(立即加载)"

 测试:

    public void test3(){
        SqlSessionUtils sqlSessionUtils = new SqlSessionUtils();
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp empAndDeptByStep = mapper.getEmpAndDeptByStep(1);
        System.out.println(empAndDeptByStep.getEmpName());

    }

未开启延迟加载(执行了2次SQL): 

开启延迟加载:

    <settings>
 
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

 执行了1次SQL:

3.一对多映射处理

1.collection

接口:

Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);

 实体类中,添加 emps集合:

 DeptMapper.xml:

collection :设置一对多的映射关系
ofType :设置 collection 标签所处理的集合属性中存储数据的类型
    <resultMap id="DeptAndEmpByDeptIdResultMap" type="Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="emps"  ofType="Emp">
            <id column="emp_id" property="empId"></id>
            <result column="emp_name" property="empName"></result>
            <result column="age" property="age"></result>
            <result column="gender" property="gender"></result>

        </collection>



    </resultMap>


    <select id="getDeptAndEmpByDeptId" resultMap="DeptAndEmpByDeptIdResultMap">
      SELECT t_emp.*,t_dept.* FROM t_dept
      LEFT JOIN t_emp
      ON t_emp.dept_id=t_dept.dept_id
      WHERE t_dept.dept_id=#{deptId}
    </select>

测试:

    public void test4(){
        SqlSessionUtils sqlSessionUtils = new SqlSessionUtils();
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept deptAndEmpByDeptId = mapper.getDeptAndEmpByDeptId(1);
        System.out.println(deptAndEmpByDeptId);


    }

运行结果: 

2.分步查询

①查询部门信息
    Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);

    <resultMap id="DeptAndEmpByStepResultMap" type="Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="emps"
                    select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                    column="dept_id">
            
        </collection>

    </resultMap>

    <select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepResultMap">
        select * from t_dept where dept_id=#{deptId}
    </select>

②根据部门 id 查询部门中的所有员工
    List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);
    <select id="getDeptAndEmpByStepTwo" resultType="Emp">
         select * from t_emp where dept_id=#{deptId}
    </select>

测试:

    public void test5(){
        SqlSessionUtils sqlSessionUtils = new SqlSessionUtils();
        SqlSession sqlSession = sqlSessionUtils.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept deptAndEmpByStepOne = mapper.getDeptAndEmpByStepOne(1);
        System.out.println(deptAndEmpByStepOne);


    }

有关【MyBatis】自定义映射resultMap的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  5. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  6. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  7. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  8. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  9. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  10. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

随机推荐