如何在 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 集群