如何在 Amazon Redshift 中使用 Hibernate 插入实体

Posted

技术标签:

【中文标题】如何在 Amazon Redshift 中使用 Hibernate 插入实体【英文标题】:How to insert entity using Hibernate in Amazon Redshift 【发布时间】:2018-10-24 14:49:57 【问题描述】:

我正在尝试使用 Hibernate 向表中插入内容。 问题是 Redshift 不接受序列,而是接受为一行创建 IDENTITY。

我有以下场景:

我的表结构:

CREATE TABLE rsds_ops_latam.log( idlog BIGINT PRIMARY KEY IDENTITY(0,1), idaccount varchar(255), username varchar(255), oldowner varchar(255), newowner varchar(255), oldclass varchar(255), newclass varchar(255), date timestamp DEFAULT GETDATE() );

我的实体:

@Entity
@NamedQuery(name="Log.findAll", query="SELECT l FROM Log l")
@Table(name = "log")
public class Log implements Serializable 
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "idlog")
private long idLog;

private String userName;

@Temporal(TemporalType.TIMESTAMP)
@GeneratedValue()
@Column(name = "date")
private Date date;

@Column(name = "idaccount")
private String idAccount;

@Column(name = "oldowner")
private String oldOwner;

@Column(name = "newowner")
private String newOwner;

@Column(name = "oldclass")
private String oldClass;

@Column(name = "newclass")
private String newClass;

当我尝试持久化实体时,日志中会出现以下内容:

11:38:16,702 INFO  [stdout] (default task-3) Hibernate: 
11:38:16,702 INFO  [stdout] (default task-3)     insert 
11:38:16,702 INFO  [stdout] (default task-3)     into
11:38:16,702 INFO  [stdout] (default task-3)         rsds_ops_latam.log
11:38:16,702 INFO  [stdout] (default task-3)         (date, idaccount, newclass, newowner, oldclass, oldowner, userName) 
11:38:16,702 INFO  [stdout] (default task-3)     values
11:38:16,703 INFO  [stdout] (default task-3)         (?, ?, ?, ?, ?, ?, ?)
11:38:18,340 INFO  [stdout] (default task-3) Hibernate: 
11:38:18,346 INFO  [stdout] (default task-3)     select
11:38:18,347 INFO  [stdout] (default task-3)         currval('rsds_ops_latam.log_idlog_seq')
11:38:18,876 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-3) SQL Error: 500310, SQLState: 42P01
11:38:18,878 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-3) [Amazon](500310) Invalid operation: relation "rsds_ops_latam.log_idlog_seq" does not exist;

我的persistence.xml如下:

<persistence-unit name="accounts2" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <jta-data-source>java:/AccountMovementsRS</jta-data-source>
     <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect" />
        <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
        <property name="hibernate.default_schema" value="rsds_ops_latam"/>
        <property name="hibernate.connection.url" value="myconnection" />
        <property name="hibernate.connection.username" value="user" />
        <property name="hibernate.connection.password" value="password" />
         <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true"/>
        <property name="hibernate.flushMode" value="FLUSH_AUTO" />
        <property name="hibernate.hbm2ddl.auto" value="validate" />
     </properties>
</persistence-unit>

我能做什么?

谢谢!

【问题讨论】:

作为数据仓库,Amazon Redshift 通常不与 Hibernate 或 OLTP 应用程序一起使用。 Redshift 的好处不适用于小型插入/更新。使用传统的 SQL 系统进行休眠和应用程序存储会更好。 我理解并同意你的观点。 【参考方案1】:

Redshift 基于 Postgres,但缺少许多 Postgres 功能。其中之一是序列。 您可以尝试使用 [GenerationType.TABLE]( https://docs.oracle.com/javaee/7/api/javax/persistence/GenerationType.html#TABLE) 。然后 Hibernate 应该创建一个表,该表将与序列类似地使用,并且应该在 plain sql 中执行(与 Redshift 兼容)。

请注意,这种方法会降低性能,因为 hibernate 会为每个插入锁定序列表,这可能会导致代价高昂。

我也支持@John 的观点,即 Redshift 不适合单次插入(因此缺少功能)。

【讨论】:

以上是关于如何在 Amazon Redshift 中使用 Hibernate 插入实体的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Amazon Redshift 中的临时表列更新现有表中的列?

如何更新 Amazon Redshift 上的 Python 库?

如何从我的 Amazon EC2 实例中连接到 Amazon Redshift 集群

如何使用 Pentaho 处理 Amazon Redshift 中缓慢变化的维度?

如何在 Amazon Redshift 中定期插入数据?

如何在 Amazon Redshift 中将整数转换为位字符串?