使用反射API向H2数据库插入数据时遇表不存在问题求助
解决H2数据库"Table PERSON not found"异常
看起来你的问题主要出在两个核心点上:数据库连接实例不匹配,以及目标数据库中缺少PERSON表。下面是具体的排查和修复步骤:
1. 修正数据库连接URL,确保代码和控制台使用同一数据库实例
你的代码中buildConnection()方法使用的连接URL是:
"jdbc:h2:C:\\Users\\biplab.musib\\eclipse-workspace\\ReflectionProject\\db-files\\db-files"
而H2控制台使用的URL是:
jdbc:h2:C:\Users\biplab.musib\eclipse-workspace\ReflectionProject\db-files\db-reflection
这意味着你的代码和控制台连接的是两个完全独立的H2数据库文件(分别对应db-files.mv.db和db-reflection.mv.db)。你在控制台中创建的PERSON表只存在于db-reflection数据库中,而代码连接的db-files数据库里根本没有这个表,所以必然会抛出找不到表的异常。
修复方法:
修改buildConnection()中的URL,和控制台保持一致:
public Connection buildConnection() throws SQLException { Connection con = DriverManager.getConnection( "jdbc:h2:C:\\Users\\biplab.musib\\eclipse-workspace\\ReflectionProject\\db-files\\db-reflection", "sa", "" ); return con; }
2. 确保PERSON表已在目标数据库中创建
即使修正了连接URL,如果数据库里还没有PERSON表,插入操作依然会失败。你可以选择手动建表或者在代码中自动生成建表逻辑:
手动建表(适合测试阶段)
打开H2控制台,连接到db-reflection数据库,执行以下SQL语句创建表:
CREATE TABLE PERSON ( p_id INT PRIMARY KEY, c_name VARCHAR(255), c_age INT );
注意字段名要和你的@PrimaryKey、@Column注解中指定的name属性完全匹配(p_id、c_name、c_age)。
自动建表(适合生产/自动化场景)
你可以扩展你的MetaModel类,添加建表逻辑,在插入数据前先检查表是否存在,不存在则自动创建:
public String buildCreateTableRequest() { StringBuilder sql = new StringBuilder("CREATE TABLE IF NOT EXISTS "); sql.append(this.clss.getSimpleName()).append(" ("); // 添加主键字段 PrimaryKeyField pk = getPrimaryKey(); sql.append(pk.getName()).append(" ").append(getSqlType(pk.getType())).append(" PRIMARY KEY"); // 添加普通列字段 for (ColumnField column : getColumn()) { sql.append(", ").append(column.getName()).append(" ").append(getSqlType(column.getType())); } sql.append(")"); return sql.toString(); } // 辅助方法:将Java类型映射为H2 SQL类型 private String getSqlType(Class<?> type) { if (type == Integer.class) { return "INT"; } else if (type == String.class) { return "VARCHAR(255)"; } // 可根据需要扩展更多类型支持 return "VARCHAR(255)"; }
然后在persist()方法中先执行建表操作:
public void persist(T t) throws IllegalArgumentException, IllegalAccessException, SQLException { MetaModel metaModel = MetaModel.of(t.getClass()); // 先建表(如果不存在) try(PreparedStatement createStmt = buildConnection().prepareStatement(metaModel.buildCreateTableRequest())){ createStmt.executeUpdate(); } // 再执行插入逻辑 String sql = metaModel.buildInsertRequest(); try(PreparedStatement statement = prepareStatementWith(sql).andParameters(t)){ statement.executeUpdate(); } }
3. 额外检查:H2数据库大小写敏感设置
H2默认对表名大小写不敏感,但如果你的数据库启用了大小写敏感模式,可能会导致Person和PERSON被视为不同的表。可以在连接URL中添加参数强制表名统一:
"jdbc:h2:C:\\Users\\biplab.musib\\eclipse-workspace\\ReflectionProject\\db-files\\db-reflection;DATABASE_TO_LOWER=TRUE"
按照以上步骤操作后,你的插入操作应该就能正常执行了。
内容的提问来源于stack exchange,提问作者Tech_sharma
相关产品推荐
相关产品推荐

