我正在尝试使用
将新用户从休眠状态插入到Firebird数据库中Session session = factory.openSession();
UserDetail user = new UserDetail();
user.setName("Mark");
user.setPassword("1234567");
user.setUserType(1L);
session.beginTransaction();
try {
session.persist(user);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
} finally {
session.close();
}
我的实体是
@Entity
@Table(name = "USER_DETAIL")
public class UserDetail
{
@Id
@Column(name = "ID", nullable = false)
@SequenceGenerator(name = "gen", sequenceName = "GEN_USER_DETAIL_ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "gen")
private Long id;
@Column(name = "TYPE_ID")
@NotNull
private Long userType;
@Column(name = "NAME")
@NotNull
@Size(min = UserDetailConstraint.MIN_USER_NAME, max = UserDetailConstraint.MAX_USER_NAME)
private String name;
@Column(name = "HASHED_PASSWORD")
@NotNull
@Size(min = UserDetailConstraint.MIN_PASSWORD, max = UserDetailConstraint.MAX_PASSWORD)
private String password;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getUserType() { return userType; }
public void setUserType(Long userType) { this.userType = userType; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
但是当hibernate尝试通过生成器检索新的id时,它使用
select next_val as id_val from GEN_USER_DETAIL_ID with lock
但是GEN_USER_DETAIL_ID
不是表,它是一个序列。
因此程序崩溃并出现错误
WARN: HHH10001002: Using Hibernate built-in connection pool (not for
production use!)
апр 26, 2017 5:19:06 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.firebirdsql.jdbc.FBDriver] at URL [jdbc:firebirdsql://localhost:3050/warehouse]
апр 26, 2017 5:19:06 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=SYSDBA, password=****}
апр 26, 2017 5:19:06 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
апр 26, 2017 5:19:06 PM org.hibernate.engine.jdbc.connections.internal.PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 5 (min=1)
апр 26, 2017 5:19:06 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.FirebirdDialect
апр 26, 2017 5:19:06 PM org.hibernate.id.enhanced.SequenceStyleGenerator configure
INFO: HHH000107: Forcing table use for sequence-style generator due to pooled optimizer selection where db does not support pooled sequences
апр 26, 2017 5:19:07 PM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 4.3.2.Final
Hibernate: select next_val as id_val from GEN_USER_DETAIL_ID with lock
апр 26, 2017 5:19:07 PM org.hibernate.id.enhanced.TableStructure$1$1 execute
ERROR: could not read a hi value
org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544569. Dynamic SQL Error
SQL error code = -204
Table unknown
GEN_USER_DETAIL_ID
At line 1, column 51
当我使用xml映射而不是注释时,一切正常。
我该如何解决这个问题?
答案 0 :(得分:2)
我找到了一种使用火鸟发生器的方法。需要这个。
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "gen")
@GenericGenerator(name = "gen", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {@org.hibernate.annotations.Parameter(name = "sequence_name", value = "GEN_USER_DETAIL_ID")
})
答案 1 :(得分:1)
@SequenceGenerator
默认分配大小为50,这需要池化序列。 Firebird不支持池化序列(技术上支持它,但不支持Hibernate所需的方式)。除1之外的分配大小会触发Hibernate来使用基于表的策略。
这在日志中也有说明:
апр26,20175:19:06 PM org.hibernate.id.enhanced.SequenceStyleGenerator配置
信息:HHH000107:由于汇总优化器选择而强制表用于序列式生成器,其中db不支持池化序列
由于您没有该表,因此会出现错误。
有几种解决方案:
将分配大小更改为1
@SequenceGenerator(name = "gen",
sequenceName = "GEN_USER_DETAIL_ID",
allocationSize = 1)
改为创建必要的表格并用1行填充:
drop sequence GEN_USER_DETAIL_ID;
commit;
create table GEN_USER_DETAIL_ID (
next_val INTEGER NOT NULL
);
commit;
insert into GEN_USER_DETAIL_ID (next_val) values (1);
commit;
创建一个触发器来分配id(或者,如果您使用的是Firebird 3,您也可以将该列声明为GENERATED BY DEFAULT AS IDENTITY
)
set term #;
create trigger user_detail_bi before insert on user_detail
as
begin
new.id = next value for GEN_USER_DETAIL_ID;
end#
set term ;#
commit;
并将@GeneratedValue
更改为IDENTITY
:
@Id
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
选项2和3可能更适合性能。