我有一个包含四列的表“groups”。数据库是postgres,group_id列是Serial。所以实际上它是一个带有默认值的Integer来获得下一个值。
我有一个用例,我需要使用@SQLInsert(使用普通的persist方法不是一个选项),但是我无法使用默认设置。这就是我所拥有的:
@SQLInsert(sql="INSERT INTO groups (group_id, parent_id, group_name, version) VALUES (DEFAULT,?,?,?)")
我将实体属性设置为其中group_id和version为null的值,另外两个是正确填充的。 group_id在DB中不可为空,版本可以为null。
我得到了这个例外:
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使相同的事情发生。
答案 0 :(得分:0)
如果要保存的类成员不是引用类型,则它们不能保存空值。它可能是与数据库记录同步失败的原因。尝试使用Integer和Double等引用类型。并确保使用直接插入查询假定默认值。
错误消息中的另一件事。它可能是默认值超出了您在Java中为该列使用的类型的边界。检查默认值是否在范围内。如果为您的班级成员设置了超出范围的值,则无法同步该值。
编辑:对不起,在这种情况下,第二部分不正确。
答案 1 :(得分: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");
...
}