通用mapper:无法获取实体类XXXXXX对应的表名

博客讲述了在项目启动时遇到通用Mapper无法获取实体类对应表名的错误。问题出在启动类使用了错误的@MapperScan注解。通过将org包的@MapperScan替换为tk包的@MapperScan注解,成功解决了该问题。该问题出现在实现ServletContextListener接口的监听器类中,对注入的业务service接口进行操作时触发。

通用mapper:无法获取实体类XXXXXX对应的表名!

错误截图:

在这里插入图片描述
进入报错方法:报错的因为获取到entityTable对象为空

public static EntityTable getEntityTable(Class<?> entityClass) {
        EntityTable entityTable = (EntityTable)entityTableMap.get(entityClass);
        if (entityTable == null) {
            throw new MapperException("无法获取实体类" + entityClass.getCanonicalName() + "对应的表名!");
        } else {
            return entityTable;
        }
    }

为空的原因则是因为:entityTableMap 中没有数据,而entityTableMap 是初始化的时候就会加载的

public static synchronized void initEntityNameMap(Class<?> entityClass, Config config) {
        if (entityTableMap.get(entityClass) == null) {
            Style style = config.getStyle();
            if (entityClass.isAnnotationPresent(NameStyle.class)) {
                NameStyle nameStyle = (NameStyle)entityClass.getAnnotation(NameStyle.class);
                style = nameStyle.value();
            }

            EntityTable entityTable = null;
            Table fields;
            if (entityClass.isAnnotationPresent(Table.class)) {
                fields = (Table)entityClass.getAnnotation(Table.class);
                if (!fields.name().equals("")) {
                    entityTable = new EntityTable(entityClass);
                    entityTable.setTable(fields);
                }
            }

            if (entityTable == null) {
                entityTable = new EntityTable(entityClass);
                entityTable.setName(StringUtil.convertByStyle(entityClass.getSimpleName(), style));
            }

            entityTable.setEntityClassColumns(new LinkedHashSet());
            entityTable.setEntityClassPKColumns(new LinkedHashSet());
            fields = null;
            List fields;
            if (config.isEnableMethodAnnotation()) {
                fields = FieldHelper.getAll(entityClass);
            } else {
                fields = FieldHelper.getFields(entityClass);
            }

            Iterator var5 = fields.iterator();

            while(true) {
                EntityField field;
                do {
                    if (!var5.hasNext()) {
                        if (entityTable.getEntityClassPKColumns().size() == 0) {
                            entityTable.setEntityClassPKColumns(entityTable.getEntityClassColumns());
                        }

                        entityTable.initPropertyMap();
                        entityTableMap.put(entityClass, entityTable);
                        return;
                    }

                    field = (EntityField)var5.next();
                } while(config.isUseSimpleType() && !SimpleTypeUtil.isSimpleType(field.getJavaType()));

                processField(entityTable, style, field);
            }
        }
    }

所以问题就出在了项目加载时,经搜索引擎找到解决的方法是:

  • 我的启动类用了org包的@MapperScan注解去扫描,将其替换成tk包的@MapperScan注解即可解决
    在这里插入图片描述

我出现该bug场景是在实现ServletContextListener接口写的一个项目监听器类里,需要启动时候去调用某个方法;

在注入业务service接口时,项目启动则产生上面的报错,特此记录一波
在这里插入图片描述

### 问题分析 在使用 `Example example = new Example(AuthStrategy.class);` 时,出现 `tk.mybatis.mapper.MapperException: 无法获取实体类对应` 的异常,主要原因是 MyBatis 无法正确识别实体类与数据库之间的映射关系。这种问题通常发生在以下几种情况: - 实体类未正确使用 `@Table` 注解指定。 - 使用了错误的 `@Entity` 注解(如 Hibernate 的 `@org.hibernate.annotations.Entity` 而非 `@javax.persistence.Entity`)。 - `MapperScan` 注解导入错误(如使用了 `import org.mybatis.spring.annotation.MapperScan` 而非 `import tk.mybatis.spring.annotation.MapperScan`)。 - 在某些容器(如 IBM Liberty)中,类加载器行为不同,导致 `entityTable` 被清空,从而无法获取[^3]。 --- ### 解决方案 #### 1. 确保实体类正确映射 使用 `@Table` 注解可以显式指定数据库,确保实体类与数据库之间正确映射: ```java import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "auth_strategy") public class AuthStrategy { // 类内容 } ``` #### 2. 使用正确的 `@Entity` 注解 确保实体类使用的是 `javax.persistence` 包下的 `@Entity` 和 `@Table` 注解,而非 Hibernate 自定义的注解。错误地使用 `org.hibernate.annotations.Entity` 可能导致映射失败[^1]。 #### 3. 确保 `MapperScan` 导入正确 在 Spring Boot 项目中,应使用 `tk.mybatis.spring.annotation.MapperScan` 注解来启用 MyBatis 的 Mapper 扫描功能。错误地导入 `org.mybatis.spring.annotation.MapperScan` 会导致 MyBatis 无法正确识别实体类的映射关系。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import tk.mybatis.spring.annotation.MapperScan; @SpringBootApplication @MapperScan(basePackages = "com.example.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` #### 4. 手动初始化实体类映射 在某些测试环境中,MyBatis 无法自动识别实体类的映射信息。可以通过手动初始化实体类的映射关系来解决该问题: ```java @Before public void setUp() { Config config = new Config(); EntityHelper.initEntityNameMap(AuthStrategy.class, config); } ``` 上述代码应在 `Example` 实例化之前调用,例如在 JUnit 测试的 `@Before` 方法中执行[^4]。 #### 5. 修复类加载器导致的 `entityTable` 问题 在某些容器(如 IBM Liberty)中,类加载器行为不同,导致 `entityTable` 被清空,从而无法获取。可以自行创建 `MapperCacheDisabler.java` 并替换 jar 包中的文件,以解决该问题[^3]。 ```java public class MapperCacheDisabler { static { // 禁用缓存,防止 entityTable 被清空 System.setProperty("tk.mybatis.mapper.entity.disableEntityTableCache", "true"); } } ``` --- ### 示例代码 以下是一个完整的实体类和使用 `Example` 查询的示例: ```java import javax.persistence.Entity; import javax.persistence.Table; import javax.persistence.Id; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Column; @Entity @Table(name = "auth_strategy") public class AuthStrategy { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "strategy_name") private String name; private String description; // Getter 和 Setter 方法 } ``` ```java @Before public void setUp() { Config config = new Config(); EntityHelper.initEntityNameMap(AuthStrategy.class, config); } @Test public void testExample() { Example example = new Example(AuthStrategy.class); example.createCriteria().andEqualTo("name", "RBAC"); List<AuthStrategy> strategies = authStrategyMapper.selectByExample(example); assertNotNull(strategies); } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值