Dreampie/Resty

动态创建的表,必须重启程序,才能对数据进行Save操作

ptlinyi opened this issue · 20 comments

创建表是用:
Record rdo = new Record();
rdo.execute("create table ......");

之后执行查询没问题,但一旦要执行record.Save就出问题了,提示“he attribute name is not exists: fieldname"
经过调试,发现有TableMeta,但其中的columns的size等于零,也就是没有取到字段!

看看是否能够在发现columns没内容时,自动重取TableMeta,或者把BuildTableMeta的方法提供出来,让我们在外面可以强制重新获取字段内容。

谢谢!

调试了吗?为什么没有加载?

没有调试的很具体,但是如果我改为创建表之后马上建立一个Record的话(同一个事务),就有成功获取到表结构。如果没有马上获取的话,待后续请求再获取,就不行了。

https://github.com/Dreampie/Resty/blob/master/resty-orm/src/main/java/cn/dreampie/orm/TableMetaBuilder.java
表结构获取代码,还请帮忙调试,或者提供一个简单的可测试代码

我因为对java不熟,调试不出来,能不能这样,你的代码里,在判断表结构缓存的时候,如果列是空的(1列都没有),就重新取一次表结构?或者取表结构的时候,如果取的列是空的,干脆就不要存起来了。

贴一段测试代码给我吧,不知道原因就不能写出正确的代码,要对其他使用的人负责

这是表结构更新的代码,没有打@transaction,但调用它的上级函数打了@transaction
`
//3.根据数据结构进行更新数据库

    Record rdo = new Record();
    for (Map.Entry<String, JSONObject> entry : updateTableList.entrySet()) {
        JSONObject jsonTable = entry.getValue();
        String tableName = getRealTableName(entId,appId, entry.getKey());
        List<Record> dbSchema = getTableSchema(tableName);
        if (dbSchema == null) {
            //创建表结构
            String createSql = makeCreateTableSql(tableName, jsonTable);
            rdo.execute(createSql);
        } else {
            //对比表结构
            //删除字段、新增字段、改变字段类型,改变是否null,改变default,改变索引
            String changeSql = makeAlertTableSql(tableName, jsonTable, dbSchema);
            if (changeSql != null) {
                rdo.execute(changeSql);
            }
        }
        Record rdoTheTable=new Record(new TableSetting(tableName));
    }

`

//这是生成创建表的代码
`
private static String makeCreateTableSql(String tableName, JSONObject jsonTable) {

    StringBuilder sb = new StringBuilder();
    int tableVer = jsonTable.getInteger("version");
    JSONArray jsonFields = jsonTable.getJSONArray("fields");
    sb.append("CREATE TABLE `" + tableName + "` ( ");
    sb.append("`id` INT NOT NULL AUTO_INCREMENT");
    for (int i = 0; i < jsonFields.size(); i++) {
        JSONObject jsonField = jsonFields.getJSONObject(i);
        sb.append(String.format(", `%s` %s %s %s",
                jsonField.getString("name"),
                jsonField.getString("type"),
                GetIsNullString(jsonField),
                GetDefaultString(jsonField, false)
        ));
    }
    sb.append(", PRIMARY KEY (`id`));");
    String sql = sb.toString();
    return sb.toString();
}

`
至于后续的查询,就是正常用的调用Record.FindColsBy之类的各种查询了

你这个我也没发直接运行啊,我根据你的描述模拟一下看看,如果你能提供可以执行运行的测试用例最好

https://github.com/Dreampie/Resty/blob/master/resty-example/src/test/java/cn/dreampie/example/SqlTest.java 从测试代码来看结果没有问题,你可以看看testTable方法运行一下,如果和你的有不同看看能不能给我一个模拟

image

即使分成两个测试方法

@FixMethodOrder(MethodSorters.JVM)
public class SqlTest {

  private static final String tableName = "tst_" + new Date().getTime();

  @BeforeClass
  public static void init() {
    ActiveRecord.init();
  }


  @Test
  public void testTable() {
    Record recordDAO = new Record();
    recordDAO.execute("CREATE TABLE " + tableName + "(id INT NOT NULL AUTO_INCREMENT,name VARCHAR(100) NOT NULL,PRIMARY KEY(id));");
  }


  @Test
  public void testColumn() {
    Record tstDAO = new Record(new TableSetting(tableName));
    Iterator iterator = tstDAO.getTableMeta().getColumnMetadata().values().iterator();
    while (iterator.hasNext()) {
      System.out.println(iterator.next().toString());
    }
  }
}

image

好的,我试试写一个DEMO出来

@Dreampie 我找到原因了,是由于表还未建立之前,先尝试用Record进行查询,这时虽然表不存在,但依然会产生一个columns为空的TableMeta,之后再创建表,再之后插入记录时,由于TableMeta已存在,导致不会重新获取columns,就会导致这个问题。
�测试步骤如下,表名为: table1,这时在mysql里这个表还不存在:
(1)Record rdoData = new Record(new TableSetting(tableName));
(2)执行创建表的sql语句
(3)再用Record.Save方法新增行
这样一定会产生“he attribute name is not exists: fieldname"的问题

没有输出警告和报错吗?表不存在你是不能直接这个new Record的啊 Failed to retrieve metadata for table: '%s'. Are you sure this table exists? For some databases table name are case sensitive.

我会处理一下没有获取的columns的情况 不加入Metadata

主要是因为我的表是动态的,new Record之前并不确定这个表是否存在的。

那new record也会报表不存在的错误,你再试试新代码

我看了你的代码修改,相信这样是没问题的了,不过因为项目是用maven管理的,而不是git clone下来的,那我怎样能获取到新代码?

1.3.0-snapshot,有网情况下直接启动会自动下载

好的,谢谢

测试正常了。不过发现resty-client没有1.3.0-snapshot的版本,其他组件都有。

resty-httpclient 避免和其他client有冲突改名了

好的