Hibernate在每次插入之前选择标识列值

时间:2019-01-21 13:54:21

标签: java hibernate sql-insert

我试图在数据库中插入30行,ID生成策略为IDENTITY,而我的数据库(Exasol)支持它。每次插入之前,Hibernate都会从数据库中选择标识值,如下所示(从Hibernate日志中):

Hibernate:
    SELECT
            COLUMN_IDENTITY 
        FROM
            EXA_ALL_COLUMNS 
        WHERE
            COLUMN_NAME='ENTRY_ID' 
            AND COLUMN_SCHEMA='TEST' 
            AND COLUMN_TABLE='CAMPAIGN'
Hibernate: 
    insert 
    into
        ecombi_mdm_test.CSV_ADCAMPAIGN
        (bla1, bla2, bla3, bla4, bla5, bla6, bla7, bla8, bla9, bla10, bla11, bla12, bla13, bla14, bla15, bla16, bla17, bla18, bla19, bla20, bla21, bla22, bla23, bla24, bla25, bla26, bla27, bla28, bla29, bla30) 
    values
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
    SELECT
            COLUMN_IDENTITY 
        FROM
            EXA_ALL_COLUMNS 
        WHERE
            COLUMN_NAME='ENTRY_ID' 
            AND COLUMN_SCHEMA='TEST' 
            AND COLUMN_TABLE='CAMPAIGN'
Hibernate: 
    insert 
    into
        ecombi_mdm_test.CSV_ADCAMPAIGN
        (bla1, bla2, bla3, bla4, bla5, bla6, bla7, bla8, bla9, bla10, bla11, bla12, bla13, bla14, bla15, bla16, bla17, bla18, bla19, bla20, bla21, bla22, bla23, bla24, bla25, bla26, bla27, bla28, bla29, bla30) 
    values
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

...和另外28个。最后,我花了9秒钟才能插入30行。

这是我配置数据源的方式:

        configuration = new Configuration();
        configuration.setProperty("hibernate.connection.driver_class", properties.getProperty(...);
        configuration.setProperty("hibernate.connection.url", properties.getProperty(...);
        configuration.setProperty("hibernate.connection.username", properties.getProperty(...);
        configuration.setProperty("hibernate.connection.password", properties.getProperty(...);
        configuration.setProperty("hibernate.dialect", properties.getProperty(com.bla.exasol.ExasolDialect);
        configuration.setProperty("hibernate.show_sql", "true");
        configuration.setProperty("hibernate.format_sql", "true");
        configuration.setProperty("hibernate.default_schema", properties.getProperty(...);
        configuration.addAnnotatedClass(Some.class);

        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
        SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

这是我的DAO课上的

Session session = MultiTenantDBAccess.getSessionFactory().openSession();
Transaction transaction = null;

try {
    transaction = session.beginTransaction();
    for (T o : oList) {
        session.persist(o);
    }
    transaction.commit();
} catch (HibernateException e) {
    transaction.rollback();
    e.printStackTrace();
} finally {
    session.close();
}

这是我数据库的自定义身份支持类:

public class ExasolIdentityColumnSupport extends IdentityColumnSupportImpl {

    @Override
    public String appendIdentitySelectToInsert(String arg0) {
        return arg0;
    }

    @Override
    public String getIdentityColumnString(int type) throws MappingException {
        return type==Types.BIGINT ?
                "decimal(36, 0) identity not null" :
                "decimal(19, 0) identity not null";
    }

    @Override
    public String getIdentitySelectString(String table, String column, int type) throws MappingException {
        return "SELECT COLUMN_IDENTITY FROM EXA_ALL_COLUMNS WHERE COLUMN_NAME='"+column.toUpperCase()+"' AND COLUMN_SCHEMA='"+table.substring(0, table.indexOf(".")).toUpperCase()+"' AND COLUMN_TABLE='"+(table.substring(table.indexOf(".")+1)).toUpperCase()+"'";
    }

    @Override
    public boolean hasDataTypeInIdentityColumn() {
        return false;
    }

    @Override
    public boolean supportsIdentityColumns() {
        return true;
    }

    public boolean supportsInsertSelectIdentity() {
        return false;
    }

}

我使用的数据库不支持InsertSelectIdentity是一个问题吗? Hibernate是否不能在每次插入之前不检查id值就向数据库发送30个查询?在这种情况下,我无法使用Hibernate达到比每9秒30行更好的性能吗?

2 个答案:

答案 0 :(得分:1)

需要ID,因为实体是使用ID作为键存储在会话中的。

规避数据库的唯一方法是,如果数据库支持使用序列,则使用数据库序列。

答案 1 :(得分:0)

对OLTP工作负载使用列式分析DMBS不是一个好主意:选择,插入或更新单行。

您可以使用MySQL / PostgreSQL等来存储作业状态和普遍的ORM悲伤。并将Exasol仅用于大数据批次和大导入。