异常“此类的ID必须在调用save()之前手动分配”意味着您正在使用“分配的”标识符生成策略。
Assign 允许应用程序在调用save()之前为该对象分配一个标识符。如果未指定任何元素,则这是默认策略。
如果您未定义任何策略,则hibernate默认为“已分配”。“分配”策略意味着hibernate状态希望应用程序提供自己的ID。
如果要在Oracle中使用序列ID生成器,则可以通过以下配置来使用-
如果您使用的是xml-
<id name="countryId" type="java.lang.Integer"> <column name="Country_Id" /> <generator > <param name="sequence">Country_Id_Seq</param> </generator> </id>
如果您使用的是注释-
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="Country_Id_Seq") @SequenceGenerator(name="Country_Id_Seq", sequenceName="Country_Id_Seq" ) private Integer sequence;
而且您的代码应如下所示-
Country c=new Country();c.setCountryName(request.getParameter("txtCountryName"));c.setCountryCode(request.getParameter("txtCountryCode"));Zone z=(Zone) session.get(Zone.class, new BigDecimal(request.getParameter("zoneId")));c.setZone(z);session.save(c);session.flush(); System.out.println(c.getCountryId());当执行“ session.save(c)”时,hibernate对Oracle进行以下sql调用,检索ID并将其设置在Country对象中。
select Country_Id_Seq.nextVal from dual;
触发问题
由于在插入行时使用触发器来增加ID,因此这将导致hibernate序列出现问题。Hibernate正在使用序列生成ID,而数据库正在使用触发器来增加ID。这导致id递增两次。
您可以通过以下三种方法解决此问题。
删除触发器,因为它不是必需的。
如果由于可以在应用程序外部更新表而仍需要触发器,则可以更新触发器,以便仅当在Oracle触发器的插入语句HIbernate问题中未设置 ID来从序列生成ID时,才生成ID。
创建一个自定义id生成器,该生成器使用触发器在将数据保存到db之前设置其ID。查看以下链接-https://forum.hibernate.org/viewtopic.php?t=973262



