mybatis-plus selectById方法不存在

博客提醒检查模型类是否配置了@Table、@TableName、@TableId等标签,与后端开发相关。

检查下 模型类有没有配置以下标签
@Table @TableName @TableId

<think> 我们面对的问题:实体类存在继承关系,重写MyBatis-PlusselectById方法实现多态查询。 核心需求:当我们调用MyBatis-Plus内置的selectById方法时,返回的对象能够根据数据库中的某个类型字段自动实例化为对应的子类对象。 分析:MyBatis-Plus的BaseMapper提供的selectById方法默认返回的是实体类本身。如果实体类有继承关系,我们希望根据数据库中的某个字段(如user_type)的值来返回同的子类对象,这需要利用MyBatis的结果映射(ResultMap)中的鉴别器(discriminator)功能。 但是,MyBatis-Plus默认的BaseMapper方法(如selectById)使用的是MyBatis-Plus自动生成的ResultMap,这个自动生成的ResultMap并支持多态。因此,我们需要自定义ResultMap,并在其中使用鉴别器。 然而,我们想重写selectById方法(即想在Mapper中自己写一个selectById方法覆盖默认的),那么我们可以通过配置MyBatis-Plus的全局配置,让它使用我们自定义的ResultMap,或者通过注解的方式实现。 但是,MyBatis-Plus的@TableName、@TableField等注解并支持多态映射。因此,我们需要回到MyBatis的原生配置,即使用XML配置ResultMap。 步骤: 1. 在实体类的父类上使用@TableName注解指定表名(用于MyBatis-Plus的CRUD操作)。 2. 自定义一个ResultMap,在该ResultMap中使用<discriminator>来根据某个字段值映射到同的子类。 3. 将这个自定义的ResultMap设置为MyBatis-Plus默认Mapper方法使用的ResultMap。 但是,MyBatis-Plus默认的BaseMapper方法(如selectById)使用了一个名为“baseResultMap”的ResultMap(如果使用MyBatis-Plus的代码生成器,它会自动生成一个)。所以我们可以修改这个baseResultMap,加入鉴别器。 然而,如果我们没有使用代码生成器,或者我们想保留MyBatis-Plus的自动映射功能,同时加入多态支持,我们可以这样做: 方案: 1. 在Mapper XML文件中,定义一个自定义的ResultMap(例如叫polymorphicResultMap),它继承自MyBatis-Plus自动生成的baseResultMap(如果存在的话),然后在其中添加鉴别器。 2. 然后,我们需要告诉MyBatis-Plus的BaseMapper方法使用这个自定义的ResultMap。但是,默认的selectById方法使用的是BaseMapper中定义的@ResultMap,这个我们无法直接修改。 因此,我们可能需要通过以下步骤来实现: 步骤1:在父实体类上使用@TableName注解,并指定autoResultMap=true(这个属性用于告诉MyBatis-Plus在生成ResultMap时包含其他字段,但并能解决多态问题,所以我们还是需要自定义ResultMap)。 步骤2:在Mapper XML中定义一个自定义的ResultMap,并设置type为父类,然后使用鉴别器。同时,这个ResultMap要包含父类和所有子类的属性映射。 步骤3:将自定义的ResultMap的id设置为MyBatis-Plus自动生成的baseResultMap的id(通常是表名+BaseResultMap),这样MyBatis-Plus的默认方法就会使用这个ResultMap。 但是,这样可能会覆盖MyBatis-Plus自动生成的baseResultMap,而且需要手动维护所有字段映射,比较麻烦。 另一种方案:使用MyBatis的@Result注解和@Results注解在Mapper接口的方法上定义结果映射。但是,我们想重写selectById方法,所以这个方案也符合要求。 因此,我们可能需要改变思路:利用MyBatis的全局配置,将默认的ResultMap替换为我们的多态ResultMap。但是,这需要深入理解MyBatis-Plus的自动配置机制,可能比较复杂。 经过思考,有一个相对简单的方法: 1. 在父类实体上,我们使用MyBatis-Plus的注解正常配置。 2. 在子类实体上,我们同样使用@TableName注解(指向同一张表),但是这样MyBatis-Plus会为每个子类生成一个BaseMapper,这是我们想要的。 所以,我们回到使用XML配置ResultMap,并覆盖默认的ResultMap。具体步骤: 步骤1:在Mapper XML中,重新定义baseResultMap(注意:这个baseResultMap的id必须是MyBatis-Plus默认生成的baseResultMap的id,通常为<类型>BaseResultMap,例如:UserBaseResultMap)。在这个ResultMap中使用鉴别器。 步骤2:在鉴别器中,根据某个字段的值(如user_type)来映射到同的子类。 步骤3:确保MyBatis扫描到这个Mapper XML文件。 这样,当我们调用BaseMapper的selectById方法时,它就会使用我们重新定义的baseResultMap,从而实现多态。 具体实现: 1. 实体类结构示例: // 父类 @TableName("user") public class User { private Long id; private String userType; // 用于区分子类的字段 // 其他公共字段... } // 子类1 public class AdminUser extends User { private String adminField; // 管理员特有字段 } // 子类2 public class MemberUser extends User { private String memberField; // 成员特有字段 } 2. Mapper接口: public interface UserMapper extends BaseMapper<User> { // 需要重写selectById,使用默认的 } 3. Mapper XML文件(如UserMapper.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.example.mapper.UserMapper"> <!-- 覆盖MyBatis-Plus自动生成的baseResultMap --> <resultMap id="UserBaseResultMap" type="com.example.entity.User"> <id column="id" property="id"/> <result column="user_type" property="userType"/> <!-- 这里需要包含所有公共字段的映射 --> <!-- 使用鉴别器 --> <discriminator javaType="String" column="user_type"> <case value="admin" resultType="com.example.entity.AdminUser"> <!-- 映射AdminUser特有字段 --> <result column="admin_field" property="adminField"/> </case> <case value="member" resultType="com.example.entity.MemberUser"> <!-- 映射MemberUser特有字段 --> <result column="member_field" property="memberField"/> </case> </discriminator> </resultMap> <!-- 注意:MyBatis-Plus默认的CRUD方法会使用这个baseResultMap,因为我们覆盖了它 --> </mapper> 4. 在application.yml中确保MyBatis扫描到了这个XML文件。 但是,这里有一个关键点:我们在父类的ResultMap中已经包含了公共字段的映射,然后在鉴别器的每个case中,我们只需要添加子类特有的字段映射即可。因为子类会继承父类的属性。 注意:在鉴别器中,每个case的resultType必须是子类的全限定名,而且每个子类对应的字段映射只需要写自己特有的字段。 这样,当我们调用userMapper.selectById(1)时,MyBatis会根据user_type字段的值,创建AdminUser或MemberUser对象,并将公共字段和特有字段都注入。 但是,这里有一个前提:在查询时,必须将父类和所有子类的字段都查询出来(即使用SELECT * 或列出所有字段)。因为鉴别器是在结果集映射时根据字段值来决定实例化哪个子类,然后映射该子类的特有字段。 因此,我们需要重写selectById方法,而是通过覆盖默认的ResultMap来实现多态。MyBatis-Plus的BaseMapper方法(包括selectById)都会使用这个ResultMap。 注意事项: 1. 如果使用了MyBatis-Plus的代码生成器,它可能会自动生成一个baseResultMap,我们需要在生成的XML文件中手动修改它,加入鉴别器。 2. 如果我们的项目允许使用XML,那么这种方法适用了。在注解方式下,我们无法避免重写selectById方法(因为需要在方法上使用@Results注解)。 总结:通过覆盖默认的baseResultMap,在其中加入鉴别器,我们可以实现重写selectById方法而达到多态查询的目的。 引用说明: 1. 引用[1]提到MyBatis是半自动化的ORM框架,支持结果集封装,我们可以利用其ResultMap实现多态映射。 2. 引用[2]中展示了实体类使用@TableName等注解,我们这里也需要使用这些注解来标识实体类和表的关系,但多态映射部分需要依靠XML配置。 3. 引用[3]提到使用代码生成器,如果使用生成器,我们需要调整生成器模板,使其生成的ResultMap包含鉴别器,或者生成后手动修改。 因此,最终方案是:通过XML配置覆盖默认的baseResultMap,使用MyBatis的鉴别器实现多态。 </think>### 实体类存在继承关系时,重写 `selectById` 实现多态查询的方案 在 MyBatis-Plus 中,当实体类存在继承关系时,可以通过 **自定义结果映射(ResultMap)** 实现多态查询,无需重写 `selectById` 方法。以下是具体实现步骤: --- #### 1. **数据库设计(关键步骤)📌** 在表中添加 **类型标识字段**(如 `user_type`),用于区分同子类: ```sql CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), user_type VARCHAR(20), -- 类型标识字段(admin/member) department VARCHAR(50), -- 管理员特有字段 level INT -- 会员特有字段 ); ``` --- #### 2. **实体类继承结构** ```java // 父类(使用 @TableName 注解) @TableName("user") public class User { private Long id; private String name; private String userType; // 类型标识字段 } // 子类 Admin public class Admin extends User { private String department; // 管理员特有字段 } // 子类 Member public class Member extends User { private Integer level; // 会员特有字段 } ``` --- #### 3. **自定义 ResultMap 实现多态映射(核心)✨** 在 Mapper XML 文件中定义包含鉴别器(`<discriminator>`)的 ResultMap: ```xml <!-- UserMapper.xml --> <resultMap id="PolymorphicUserMap" type="com.example.User"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="user_type" property="userType"/> <!-- 多态鉴别器 --> <discriminator javaType="String" column="user_type"> <case value="admin" resultType="com.example.Admin"> <result column="department" property="department"/> </case> <case value="member" resultType="com.example.Member"> <result column="level" property="level"/> </case> </discriminator> </resultMap> ``` --- #### 4. **配置 MyBatis-Plus 使用自定义 ResultMap** 在父类实体的 Mapper 接口中指定默认 ResultMap: ```java @Mapper public interface UserMapper extends BaseMapper<User> { // 指定自定义ResultMap为默认映射 @Override @ResultMap("PolymorphicUserMap") User selectById(Serializable id); } ``` --- #### 5. **效果验证** 调用 `selectById` 时自动返回对应子类对象: ```java // 返回 Admin 实例(当 user_type='admin') Admin admin = (Admin) userMapper.selectById(1); // 返回 Member 实例(当 user_type='member') Member member = (Member) userMapper.selectById(2); ``` --- ### 关键原理说明 🔍 1. **鉴别器(Discriminator)** 根据 `user_type` 字段值动态决定实例化哪个子类,实现多态映射[^1]。 2. **MyBatis-Plus 集成** 通过 `@ResultMap` 注解覆盖默认映射规则,无需修改 BaseMapper 源码[^2]。 3. **字段映射规则** - 公共字段在父类 `<resultMap>` 中定义 - 子类特有字段在 `<case>` 中定义 - 数据库表需包含所有子类的字段(如 `department`, `level`) --- ### 对比方案优劣 | 方案 | 是否需要重写 `selectById` | 复杂度 | 可维护性 | |------|---------------------------|--------|----------| | **自定义 ResultMap** | ❌ 需要 | ★★☆ | ✅ 高 | | Service 层手动转换 | ✅ 需要 | ★☆☆ | ❌ 低 | | 重写 Mapper 方法 | ✅ 需要 | ★★★ | ⚠️ 中 | > 💡 推荐优先使用 **自定义 ResultMap** 方案,符合 MyBatis 原生设计且破坏 MyBatis-Plus 的封装性[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值