0

我有一个包含四列的表“组”。数据库是 postgres,group_id 列是 Serial。所以实际上它是一个 Integer,默认获取下一个值。

我有一个需要使用@SQLInsert 的用例(不能使用普通的持久化方法),但我无法让它与默认值一起使用。这是我所拥有的:

@SQLInsert(sql="INSERT INTO groups (group_id, parent_id, group_name, version) VALUES (DEFAULT,?,?,?)")

我将实体属性设置为 group_id 和 version 为 null 且其他两个已正确填充的值。group_id 在数据库中不可为空,版本可以为空。

我得到这个例外:

WARNING: SQL Error: 0, SQLState: 22023
SEVERE: The column index is out of range: 4, number of columns: 3.
SEVERE: Could not synchronize database state with session

如果我直接在数据库上输入以下 DML,它可以工作:

INSERT INTO groups (group_id, parent_id, group_name, version) VALUES (DEFAULT, 3, 'abcd', null); 

有没有办法使用@SQLInsert 来实现同样的事情。

4

2 回答 2

0

如果您要保存的类成员不是引用类型,则它们不能保存空值。这可能是与数据库记录同步失败的原因。尝试使用 Integer 和 Double 等引用类型。并确保使用直接插入查询假定默认值。

错误消息中的另一件事。默认值可能超出了您在 Java 中为该列使用的类型的边界。检查默认值是否在范围内。如果为您的班级成员设置了超出范围的值,则无法同步。

编辑:对不起,在这种情况下,第二部分不正确。

于 2012-06-05T11:33:04.173 回答
0

所以简短的回答是“不能这样做”。尽管我在很多地方都看到过这个问题,但 Hibernate 人员并没有提供这个用例。

我的解决方案是将 Postgres 序列与表分离。也就是说,我删除了从序列中选择 nextval 并填充两个主键字段之一的默认约束。

然后我使用本机查询手动获取 nextval(是的,强制取消抽象数据库),并使用该值手动填充主键字段。有用。它很笨拙,但我可能会更频繁地使用它。与使用纯 ORM 方法相比,发生的事情当然更容易理解。这可以在没有巫师帽的情况下进行调试。:)

public class...
@PersistenceContext(unitName = "persistence_unit")
private EntityManager em;

...
mymethod(){
...
Query q = em.createNativeQuery("SELECT nextval('groups_group_id_seq')");
BigInteger groupId = (BigInteger)q.getSingleResult();

BigInteger parentId = methodToGetParentId();

GroupsPK gpk = new GroupsPK(groupId, parentId);

Groups grps = new Groups(gpk, "other parameters");

...
}
于 2012-06-05T19:33:05.973 回答