如何使用反射 API 将数据插入 H2 数据库

Posted

技术标签:

【中文标题】如何使用反射 API 将数据插入 H2 数据库【英文标题】:how to insert data into H2 database using reflection API 【发布时间】:2020-08-01 21:04:03 【问题描述】:

我有一个用@PrimaryKey 和@Column 标注的 Person 类

    public class Person 

    @PrimaryKey(name = "p_id")
    private Integer id;

    @Column(name = "c_name")
    private String name;

    @Column(name = "c_age")
    private Integer age;
    

以下是persist方法:

   public void persist(T t) throws IllegalArgumentException, IllegalAccessException, SQLException 
    // TODO Auto-generated method stub
    MetaModel metaModel = MetaModel.of(t.getClass());
    String sql = metaModel.buildInsertRequest();

    try(PreparedStatement statement = prepareStatementWith(sql).andParameters(t))
        statement.executeUpdate();  
    



    private PreparedStatementWrapper prepareStatementWith(String sql) throws SQLException 
    // TODO Auto-generated method stub

    Connection con = buildConnection();
    PreparedStatement statement = con.prepareStatement(sql);

    return new PreparedStatementWrapper(statement);


    private class PreparedStatementWrapper

    private PreparedStatement statement;
    public PreparedStatementWrapper(PreparedStatement statement) 
        // TODO Auto-generated constructor stub
         this.statement = statement;
    

这里。返回sql查询

   public String buildInsertRequest() 
    // insert into Person(id, name, age) values(?, ?, ?)
    String pkColumnName = getPrimaryKey().getName();
    List<String> columNames = getColumn().stream().map(c -> c.getName()).collect(Collectors.toList());
    columNames.add(0, pkColumnName);
    String columnElement = String.join(", ", columNames);

    int numberOfColumns = getColumn().size() + 1;
    String questionMarkElement = IntStream.range(0, numberOfColumns)
                                            .mapToObj(index -> "?")
                                            .collect(Collectors.joining(", "));
    return "INSERT into " + this.clss.getSimpleName() + "(" + columnElement + ") values (" + questionMarkElement + ")";


   Here adding the parameter

   public PreparedStatement andParameters(T t) throws SQLException, IllegalArgumentException, IllegalAccessException 
        // TODO Auto-generated method stub

        MetaModel metaModel = MetaModel.of(t.getClass());
        Class<?> pkType = metaModel.getPrimaryKey().getType();
        if(pkType == Integer.class) 
            Integer id = idGenerator.incrementAndGet();
            statement.setInt(1, id);    
            Field field = metaModel.getPrimaryKey().getField();
            field.setAccessible(true);
            field.set(t, id);
        
        for(int columnIndex = 0; columnIndex < metaModel.getColumn().size(); columnIndex++) 
            ColumnField columnField = (ColumnField) metaModel.getColumn().get(columnIndex);
            Class<?> fieldType = columnField.getType();
            Field field = columnField.getField();
            field.setAccessible(true);
            Object value = field.get(t);
            if(fieldType == Integer.class) 
                statement.setInt(columnIndex + 2,(Integer) value);
             else if(fieldType == String.class) 
                statement.setString(columnIndex + 1, (String)value);
            
        
        return statement;
    

我在 prepareStatementWith(sql) 方法中遇到错误,它没有重新运行新的 PreparedStatementWrapper,而是抛出异常SQL 语句: 插入 Person(p_id, c_name, c_age) 值(?,?,?)

以下是连接详情:

    public Connection buildConnection() throws SQLException 
    Connection con = 
            DriverManager.getConnection("jdbc:h2:C:\\Users\\biplab.musib\\eclipse-workspace\\ReflectionProject\\db-files\\db-files", "sa", "");
    return con;

H2 提示符中的 JDBC url:jdbc:h2:C:\Users\biplab.musib\eclipse-workspace\ReflectionProject\db-files\db-reflection

有人可以帮我吗

【问题讨论】:

鉴于错误消息,您的数据库没有名为 PERSON 的表。如果您打算插入名为 Person 的表中,请确保在查询中正确引用对象名称。 我在 h2 中有一个名为 PERSON 的表,其中包含三个字段。 那我猜你没有连接到正确的数据库,因为 H2 错误信息明确表示找不到表。 【参考方案1】:

对我来说,将连接 URL 更改为与 H2 数据库连接 URL 相同:

Connection connection = DriverManager.getConnection("jdbc:h2:C:\\Users\\PUSHPENDRA KUMAR\\IdeaProjects\\PlayWithReflection\\dbfiles\\db-pluralsight","sa","");

【讨论】:

以上是关于如何使用反射 API 将数据插入 H2 数据库的主要内容,如果未能解决你的问题,请参考以下文章

数据如何插入 H2 数据库?

如何将格式为“3/22/2018 12:24:29 PM”的日期时间字符串格式化为sql时间戳以插入内存数据库中的h2?

如何在 laravel 中使用 H2 数据库?

将 WSO2API 管理器从 H2 迁移到 Mysql

在 Spring Boot 应用程序上使用 Flyway 时如何在 H2 中加载初始数据?

如何在 PHP 中使用 cURL/HTTP 将数据插入 CloudTables 数据库?错误:需要 API 密钥