mybatis表对象继承实现

elim168 elim168     2022-10-20     260

关键词:

       Mybatis表对象继承

       我们一般用表来表现对象之间的继承关系时通常有三种方式。第一种是把所有对象包含的属性都存放在一张表中,然后用一个字段来区分当前记录对应的对象类型;第二种是每个子类型一张表,每张表都存该对象所有的属性;第三种是基类作为一张表进行存储,每个子类特性的属性都新建一张表进行保存,然后在基类对应的表里面通过一个字段来区分对象的类型。第二种跟普通的处理方式没有什么区;第一种和第三种大同小异,本文将主要围绕第三种方式的实现来描述。

 

       举个例子,就拿我们的组织关系来说吧,组织上有机构、部门、岗位、人员,它们都属于组织,从对象的角度来讲,可以把它们共性的东西,如ID、上级ID、名称等抽取出来作为一个基类,其它特性的东西在子类中表现。本文只是为了表明这种继承的意思,会简化很多。为此,我们可以定义一个基类OrganizationBase,其定义如下。

/**

 * 组织基类

 *

 * @author Elim 20161217

 */

public abstract class OrganizationBase

 

   /**

    * 主键

    */

   private Long id;

   /**

    * 名称

    */

   private String name;

   /**

    * 类型,1:机构,2:部门,3:岗位,4:个人

    */

   private Integer type;

   /**

    * 父级组织的ID

    */

   private Integer parentId;

  

   protected OrganizationBase(Integer type)

      this.type = type;

  

 

   /**

    * @return the id

    */

   public Long getId()

      return id;

  

 

   /**

    * @param id

    *            the id to set

    */

   public void setId(Long id)

      this.id = id;

  

 

   /**

    * @return the name

    */

   public String getName()

      return name;

  

 

   /**

    * @param name

    *            the name to set

    */

   public void setName(String name)

      this.name = name;

  

 

   /**

    * @return the type

    */

   public Integer getType()

      return type;

  

 

   /**

    * @param type

    *            the type to set

    */

   public void setType(Integer type)

      this.type = type;

  

 

   /**

    * @return the parentId

    */

   public Integer getParentId()

      return parentId;

  

 

   /**

    * @param parentId

    *            the parentId to set

    */

   public void setParentId(Integer parentId)

      this.parentId = parentId;

  

 

 

       在基类中的type属性是用来区分组织类型的,机构、部门、岗位都没有自己的特殊属性,都完全从父类继承,但是从程序的角度来讲,它们的类定义还是需要的,为此我们定义了Organization、Department、Post类,它们的类定义的结构类似,其中Organization类的定义如下。

/**

 * 机构

 * @author Elim

 * 20161217

 */

public class Organization extends OrganizationBase

 

   public Organization()

      super(OrgType.ORG);

  

 

 

       我们给员工定义了一个Person类,其简单的扩充了mobile属性和email属性,具体定义如下。

/**

 * 员工

 * @author Elim

 * 20161217

 */

public class Person extends OrganizationBase

 

   /**

    * 员工的手机号码

    */

   private String mobile;

   /**

    * 员工的邮箱地址

    */

   private String email;

  

   public Person()

      super(OrgType.PERSON);

  

 

   /**

    * @return the mobile

    */

   public String getMobile()

      return mobile;

  

 

   /**

    * @param mobile the mobile to set

    */

   public void setMobile(String mobile)

      this.mobile = mobile;

  

 

   /**

    * @return the email

    */

   public String getEmail()

      return email;

  

 

   /**

    * @param email the email to set

    */

   public void setEmail(String email)

      this.email = email;

  

  

 

       组织基类型对应的表和员工对应的表的MySQL建表语句如下。

create table t_org(id int primary key auto_increment, name varchar(100), org_type int, parent_id int);

 

create table t_person(id int,mobile varchar(20), email varchar(100));

 

       我们的增删改查都应该是基于主表和扩展表来的,没有扩展表的除外。我们先来说增、删、改,查放到最后来说。针对OrganizationBase,我们建立对应的OrganizationBaseMapper.xml文件,其增、删、改定义如下。

   <insert id="insert"parameterType="com.elim.learn.mybatis.model.OrganizationBase"useGeneratedKeys="true" keyProperty="id" keyColumn="id">

      insert into t_org(id,name,org_type,parent_id) values(#id,#name,#type,#parentId)

   </insert>

  

   <insert id="delete" parameterType="java.lang.Long">

      delete t_org where id=#id

   </insert>

  

   <update id="update"parameterType="com.elim.learn.mybatis.model.OrganizationBase">

      update t_org

      <set>

        <if test="name != null">

           name = #name,

        </if>

        <if test="type != null">

           org_type = #type,

        </if>

        <if test="parentId != null">

           parent_id = #parentId

        </if>

      </set>

      where id = #id

   </update>

 

       对于没有扩展属性的组织来讲,其增、删、改操作直接通过基表对应的增、删、改操作即可,而对于有扩展属性的而言,其增、删、改操作应当还要包括对应的扩展表的操作,如我们的员工。针对员工信息,建立对应的PersonMapper.xml文件,其中的增、删、改定义如下。

   <insert id="insert"parameterType="com.elim.learn.mybatis.model.Person">

      insert into t_person(id,email,mobile) values(#id,#email,#mobile)

   </insert>

  

   <insert id="delete" parameterType="java.lang.Long">

      delete t_person where id=#id

   </insert>

  

   <update id="update"parameterType="com.elim.learn.mybatis.model.Person">

      update t_person

      <set>

        <if test="email != null">

           email = #email,

        </if>

        <if test="mobile != null">

           mobile = #mobile,

        </if>

      </set>

      where id = #id

   </update>

 

       我们在新增没有扩展表的记录时,只需要操作OrganizationBaseMapper中的对应操作即可,如下面示例的testInsert();而如果我们是操作有扩展表的,则需要同时操作多个Mapper,如下面示例的testInsertPerson()。

   @Test

   public void testInsert()

      Organization orgBase = new Organization();

      orgBase.setName("TEST_ORG");

      this.orgBaseMapper.insert(orgBase);

  

  

   @Test

   public void testInsertPerson()

      Person person = new Person();

      person.setName("ZhangSan");

      person.setEmail("zhangsan@163.com");

      person.setMobile("15889898989");

      person.setParentId(1);

      this.orgBaseMapper.insert(person);

      this.personMapper.insert(person);

  

 

       删与改操作是类似的,这里就不再给出对应的测试示例了,有兴趣的朋友可以自己试一下。至于查而言,那么我们又有两种方式了,一种是基表的查询只查询通用信息,其也可以通过区分字段来区分不同的类型,有需要的时候再去查子表,而子表在查询的时候将所有的信息都查询出来。另一种是直接在基表中通过左连接查询出所有的信息。这里以方式二为例,假设我们有一个根据ID查询组织的需求,我们在OrganizationBaseMapper.xml中定义了一个findById的查询,语句如下。

   <select id="findById" resultMap="baseResultMap"parameterType="java.lang.Long">

      select a.id,a.name,a.org_type,a.parent_id,b.mobile,b.email from t_org a left join t_person b on a.id=b.id where a.id=#id

   </select>

 

       接着来看一下我们的baseResultMap的定义。

   <resultMap type="com.elim.learn.mybatis.model.OrganizationBase"id="baseResultMap">

      <id column="id" property="id" />

      <result column="name" property="name" />

      <result column="parent_id" property="parentId" />

      <discriminator javaType="java.lang.Integer" column="org_type">

        <case value="1"resultType="com.elim.learn.mybatis.model.Organization" />

        <case value="2"resultType="com.elim.learn.mybatis.model.Department" />

        <case value="3"resultType="com.elim.learn.mybatis.model.Post" />

        <case value="4" resultMap="PersonResultMap" />

      </discriminator>

   </resultMap>

   <resultMap type="com.elim.learn.mybatis.model.Person"id="PersonResultMap">

      <result column="email" property="email" />

      <result column="mobile" property="mobile" />

   </resultMap>

 

       在ResultMap定义中,我们通过discriminator元素来指定类型区分列,并在其下通过case元素指定各种区分列的值对应的返回结果类型或ResultMap。我们可以看到对于没有其它扩展属性的,我们可以直接通过case元素指定返回类型,如case等于1的情况;而有扩展属性的,则可以通过case元素指定扩展属性对应的resultMap,然后再对应的resultMap中再指定扩展属性对应的映射,如case等于4的情况。其实我们也可以直接把结果集映射放到case中,但此时我们需要指定case元素的resultType属性来指定对应的类型,如:

   <resultMap type="com.elim.learn.mybatis.model.OrganizationBase"id="baseResultMap">

      <id column="id" property="id" />

      <result column="name" property="name" />

      <result column="parent_id" property="parentId" />

      <discriminator javaType="java.lang.Integer" column="org_type">

        <case value="1"resultType="com.elim.learn.mybatis.model.Organization" />

        <case value="2"resultType="com.elim.learn.mybatis.model.Department" />

        <case value="3"resultType="com.elim.learn.mybatis.model.Post" />

        <case value="4"resultType="com.elim.learn.mybatis.model.Person">

           <result column="mobile" property="mobile"/>

           <result column="email" property="email"/>

        </case>

      </discriminator>

   </resultMap>

 

       我们还可以通过resultMap的继承机制来定义结果集映射,先定义一个公共属性映射,然后在最顶层的时候就通过discriminator来区分不同的值对应不同的结果集映射,各个子类型的结果集映射都继承公用的结果集映射,如:

   <resultMap type="com.elim.learn.mybatis.model.OrganizationBase"

      id="baseResultMap">

      <discriminator javaType="java.lang.Integer" column="org_type">

        <case value="1" resultMap="OrganizationResultMap" />

        <case value="2" resultMap="DepartmentResultMap" />

        <case value="3" resultMap="PostResultMap" />

        <case value="4" resultMap="PersonResultMap" />

      </discriminator>

   </resultMap>

 

   <!-- 公共部分的结果集映射 -->

   <resultMap type="com.elim.learn.mybatis.model.OrganizationBase"

      id="OrganizationBaseResultMap">

      <id column="id" property="id" />

      <result column="name" property="name" />

      <result column="org_type" property="type" />

      <result column="parent_id" property="parentId" />

   </resultMap>

 

   <!-- 机构结果映射,继承自OrganizationBaseResultMap -->

   <resultMap type="com.elim.learn.mybatis.model.Organization"

      id="OrganizationResultMap" extends="OrganizationBaseResultMap"/>

   <resultMap type="com.elim.learn.mybatis.model.Department"id="DepartmentResultMap"

      extends="OrganizationBaseResultMap" />

   <resultMap type="com.elim.learn.mybatis.model.Post"id="PostResultMap"

      extends="OrganizationBaseResultMap" />

   <resultMap type="com.elim.learn.mybatis.model.Person"id="PersonResultMap">

      <result column="email" property="email" />

      <result column="mobile" property="mobile" />

   </resultMap>

 

参考文档

http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps

 

(注:本文是基于Mybatis3.3.1所写)

mybatis中实现多表查询

一、1、Mybatis是实现多表查询方式  1.1 业务装配:对两个表编写单表查询语句,在业务(Service)把查询的两表结果合并  1.2 使用AutoMapping特性,在实现两表联合查询时通过别名完成映射  1.3 使用MyBatis<resultMap>... 查看详情

mybatis04

一.MyBatis实现多表查询 Mybatis实现多表查询方式    1.1业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联.    1.2使用AutoMapping特性,在实现两表联合查询时通过别名完成映射.    1.3使... 查看详情

mybatis配置

MyBatis可以简化JDBC操作,实现数据的持久化    ORM:ObjectRelationalMapping 概念       person对象      person表  MyBatis是ORM的一个实现/Hibernate    ORM可以使得开发人员 像操作对象一样操... 查看详情

真正的mybatis动态sql—mybatisdynamicsql

...。可以将它看作是一个类型安全的sQL模板库,它提供了对MyBatis3和SpringJDBC模板的额外支持。该库将生成供MyBatis或Spring使用的格式化的fuLLETEINET、SELECT和UPDATE语句。最常见的用例是生成可以直接由MyBatis使用的语句和一组数学参数... 查看详情

mybatis可以像hibernate一样自动创建表吗

 以前没怎么用过mybatis,只知道与hibernate一样是个orm数据库框架。随着使用熟练度的增加,发现它与hibernate区别是非常大的,结合至今为止的经验,总结出以下几点:  1.hibernate是全自动,而mybatis是半自动。  hibernate完全... 查看详情

mybatis怎么样使用mapper3实现多表关联查询

参考技术A首先,mybatis本身不会判断是否是多表查询,mybatis的多表查询和单表查询其实没有什么区别,你都需要一个对象接收返回值。例如:selectu.namename,p.gradegradefromtable_1u,table_2pwhereu.id=p.id。这里你从两张表里查出两个字段n...... 查看详情

mybatis关联(多表)查询

一对一查询使用resultType:使pojo类继承一个表对应的javabean,添加另一个表的javabean属性。Xml配置和普通pojo是一样的使用resultMap:使pojo添加另一个表对象的javabean属性。Xml配置中使用<association property="user"javaType="user路径">... 查看详情

mybatis复习

概述mybatis是一个用java编写的持久层框架,它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程,它使用了ORM思想实现了结果集的封装ORMObjectRelationalMapping对象关系映射,把数据库表... 查看详情

简述mybatis

mybatis是一个ORM框架(持久层框架)原始的jdbc操作是面向二维表数据,不是面向对象的,很不方便,Mybatis实现了关系和对象的映射,sql结构化查询语言,不是面向对象的,而我们希望能用Java来操作,mybatis提供了字段映射和对象... 查看详情

mybatis总结

...称和pojo中属性名称的对应关系 使用collection标签6.spring和mybatis整合 整合后会话工厂都归spring管理 1)原生Dao实现: 需要在spring配置文件中指定dao实现类 dao实现类需要继承SqlSessionDaoSupport超类 在dao实现类中不要手动关闭会话,不要... 查看详情

mybatis自动生成的bo对象继承公共父类(bo中过滤掉公共属性)

使用mybatis的代码生成工具:mybatis-generator,如果自动生成的BO都有公共的属性,则可以指定这些BO继承父类(父类中定义公共属性)1、定义父类注意:属性public,不要使用private,让子类BO可以直接操作它 2、BO打jar包,并在myba... 查看详情

spring+mybatis项目中通过继承abstractroutingdatasource实现数据库热切换

 在做ERP项目的时候有个需求是能够管理和切换账套,一个账套就是一个数据库,那么就需要实现数据库的热切换。网上找了很多资料再结合项目的具体需求实现了一个还算比较好用的数据库热切换。 原理是首先继承Abstra... 查看详情

java——面向对象——继承和实现

JAVA——面向对象——继承和实现一、继承和实现概念二、继承和实现的举例一、继承和实现概念1.继承和实现的规则一个类可以实现多个接口一个接口可以继承多个接口2.继承和实现的判断类-类单继承(publicclass子类extends父... 查看详情

13对象-继承

许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。由于JS函数没有签名,在ECMAScript中无法实现接口继承。ECMAScript只支持实现继承,而且其实现继承主要是依靠原型... 查看详情

mybatis四大接口之parameterhandler

1. 继承结构  只有一个默认的实现类  2. ParameterHandler  获取参数对象;  设置参数;publicinterfaceParameterHandler{ObjectgetParameterObject();voidsetParameters(PreparedStatementps)throwsSQLException;}3. DefaultPa 查看详情

JPA 表继承和对象映射

】JPA表继承和对象映射【英文标题】:JPAtablesinheritanceandobjectmapping【发布时间】:2018-02-0316:58:25【问题描述】:是否可以将baseTable与基类映射并告诉JPA工具不要在类中插入baseTable中的文件?我在我的数据库的每个表中都有我想要... 查看详情

mybatis框架

一:什么是mybatis?mybatis是用java实现的持久层框架,他封装了jdbc的很多细节,使开发者只需关注sql语句本身,而不用管注册驱动等等繁琐的过程。它使用了ORM思想封装结果集。ORM:ObjectRelationalMappging对象关系映射。简单地说,就... 查看详情

mybatis实现关联表查询

1.在一个实体类中添加另一个实体类的属性及List属性:publicclassCourse{privateintid;//id-->cid   privateStringname;//name-->cnameprivateTeacherteacher;privateList<Student>list;2.定义SQL映射文件courseMappe 查看详情