Configure Hibernate to use Oracle's SYS_GUID() for Primary Key

匆匆过客 提交于 2019-11-29 13:44:35

You might be able to use the "guid" generator. See this post from the Hibernate forum. It looks like they added support for Oracle using SYS_GUID() a while back, but the documentation still says they only support SQL Server and MySQL.

I haven't worked with JPA annotations yet, but here is an example using XML configuration:

<id name="PRODUCT_ID">
  <generator class="guid" />
</id>

EDIT: In regards to your second question, I think you are asking why Hibernate can't do something like this:

INSERT INTO PRODUCT (PRODUCT_ID, /* etc */)
SELECT SYSGUID(), /* etc */

The reason is that Hibernate must know what the object's ID is. For example, consider the following scenario:

  1. You create a new Product object and save it. Oracle assigns the ID.
  2. You detach the Product from the Hibernate session.
  3. You later re-attach it and make some changes.
  4. You now want to persist those changes.

Without knowing the ID, Hibernate can't do this. It needs the ID in order to issue the UPDATE statement. So the implementation of org.hibernate.id.GUIDGenerator has to generate the ID beforehand, and then later on re-use it in the INSERT statement.

This is the same reason why Hibernate cannot do any batching if you use a database-generated ID (including auto-increment on databases that support it). Using one of the hilo generators, or some other Hibernate-generated ID mechanism, is the only way to get good performance when inserting lots of objects at once.

I have same task that topic starter. With thanks to @Matt Solnit suggestion I use such annotations:

@Id
@NotNull
@Column(name = "UUID")
@GenericGenerator(name = "db-uuid", strategy = "guid")
@GeneratedValue(generator = "db-uuid")
private String uuid;
public String getUuid() { return uuid; }
public void setUuid(String uuid) { this.uuid = uuid; }

strategy = "guid" and String type are essential parts of solution.

Before persisting new entities Hibernate issue SQL query:

select rawtohex(sys_guid()) from dual

My setup: Oracle 11, Hibernate 4.3.4.Final, Spring 3.2.x. And field is raw(16) in table for efficient storage and lesser index size then if you use char(32).

When I try to use java.util.UUID as ID field type I get error from Hibernate on persisting new entity (it try to set String type to java.util.UUID field).

Also I use javax.xml.bind.DatatypeConverter for non-Hibernate queries (Spring JDBC helpers), for passing convert to byte[]:

String query = "insert into TBL (UUID, COMPANY) values (:UUID, :COMPANY)";
MapSqlParameterSource parameters = new MapSqlParameterSource()
    .addValue("COMPANY", repo.getCompany())
    .addValue("UUID", DatatypeConverter.parseHexBinary(signal.getUuid()));
namedJdbcTemplate.update(query, parameters);

for extracting:

ResultSet rs;
sig.id = DatatypeConverter.printHexBinary(rs.getBytes("UUID"));

All web controllers get codes like:

025131763FB19522E050010A106D11E9

without {, -, } chars (usual representation of UUID is {a-b-c-d-x-y} if you remember). This representation already URL encoding clean and safe. You don't need to implement PropertyEditor or Convertor for String type:

@RequestMapping(value = {"/signal/edit/{id}.htm"}, method = RequestMethod.POST)
public String handleEditRequest(
        @PathVariable("id") String id,

Compare with failed attempt to use jaa.util.UUID, where I need to write:

@Component
public static class UUIDPropertyEditor extends PropertyEditorSupport {
    @Override
    public void setAsText(final String str) {
        if (str == null || str.isEmpty()) {
            setValue(null);
            return;
        }
        setValue(UUID.fromString(str));
    }
}
private @Autowired UUIDPropertyEditor juuidPE;

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(UUIDPropertyEditor.class, juuidPE);
}

in order to use:

@PathVariable("id") UUID id,

I think you can do it by setting the generator to native. I'm not really sure how to do it in Hibernate but in NHibernate you'd do something like this in the XML:

<id column="PRODUCT_ID">
  <generator class="native"/>
</id>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!