我正在寻找一种让hibernate在插入新行时使用oracle的SYS_GUID()
函数的方法。目前我的数据库表有SYS_GUID()
作为默认值,所以如果hibernate只是生成了SQL,它会省略它应该工作的值。
我已经完成了所有工作,但它目前正在使用system-uuid生成器在代码中生成UUID / GUID:
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "PRODUCT_ID", unique = true, nullable = false)
public String getId() {
return this.productId;
}
这很好,但我更希望guid是由数据库生成的,因此它们将是顺序的,并且可能具有更好的性能。另外,我想知道如何配置它。
我正在使用注释进行配置,但xml配置示例也很棒。
以下是一个示例表定义(如果重要):
CREATE TABLE SCHEMA_NAME.PRODUCT
(
PRODUCT_ID RAW(16) DEFAULT SYS_GUID() NOT NULL,
PRODUCT_CODE VARCHAR2(10 CHAR) NOT NULL,
PRODUCT_NAME VARCHAR2(30 CHAR) NOT NULL,
PRODUCT_DESC VARCHAR2(512 CHAR)
)
Mat使用“guid”解决了这个问题,这里是sql生成的:
Hibernate:
select rawtohex(sys_guid())
from dual
Hibernate:
insert into PRODUCT
(PRODUCT_CODE, PRODUCT_DESC, LOB_ID, PRODUCT_NAME, PROVIDER_ID, PRODUCT_ID)
values (?, ?, ?, ?, ?, ?)
似乎无法在插入中使用列默认值,因此可以选择在应用程序生成的guid和数据库往返之间。
答案 0 :(得分:5)
您可以使用“guid”生成器。请参阅Hibernate论坛中的this post。看起来他们前一段时间使用SYS_GUID()
添加了对Oracle的支持,但documentation仍然表示他们只支持SQL Server和MySQL。
我还没有使用过JPA注释,但这里有一个使用XML配置的例子:
<id name="PRODUCT_ID">
<generator class="guid" />
</id>
编辑:关于你的第二个问题,我想你在问为什么Hibernate不能做这样的事情:
INSERT INTO PRODUCT (PRODUCT_ID, /* etc */)
SELECT SYSGUID(), /* etc */
原因是Hibernate必须知道对象的ID是什么。例如,请考虑以下情形:
在不知道ID的情况下,Hibernate无法做到这一点。它需要ID才能发出UPDATE语句。因此org.hibernate.id.GUIDGenerator
的实现必须事先生成ID,然后再在INSERT语句中重用它。
如果您使用数据库生成的ID(包括支持它的数据库的自动增量),这就是Hibernate无法执行任何批处理的原因。使用其中一个hilo生成器或其他一些Hibernate生成的ID机制,是在一次插入大量对象时获得良好性能的唯一方法。
答案 1 :(得分:1)
我有与主题启动器相同的任务。感谢 @Matt Solnit 建议,我使用了这样的注释:
@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"
和String
类型是解决方案的重要组成部分。
在持久化新实体之前,Hibernate会发出SQL查询:
select rawtohex(sys_guid()) from dual
我的设置:Oracle 11,Hibernate 4.3.4.Final,Spring 3.2.x.如果您使用raw(16)
,那么表中的字段为char(32)
,用于高效存储和较小的索引大小。
当我尝试将java.util.UUID
用作ID字段类型时,我会在持久化新实体时从Hibernate收到错误(它会尝试将String
类型设置为java.util.UUID
字段。
我还使用javax.xml.bind.DatatypeConverter
进行非Hibernate查询(Spring JDBC帮助程序),以便将转换传递给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);
用于提取:
ResultSet rs;
sig.id = DatatypeConverter.printHexBinary(rs.getBytes("UUID"));
所有网络控制器都会获得如下代码:
025131763FB19522E050010A106D11E9
没有{
,-
,}
字符(如果您记得的话,UUID的常规表示为{a-b-c-d-x-y}
)。此表示已经URL编码干净且安全。您不需要为PropertyEditor
类型实施Convertor
或String
:
@RequestMapping(value = {"/signal/edit/{id}.htm"}, method = RequestMethod.POST)
public String handleEditRequest(
@PathVariable("id") String id,
与尝试使用jaa.util.UUID
的失败进行比较,我需要写一下:
@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);
}
为了使用:
@PathVariable("id") UUID id,
答案 2 :(得分:0)
我认为您可以通过将生成器设置为本机来实现。我不确定如何在Hibernate中实现它,但在NHibernate中你会在XML中做这样的事情:
<id column="PRODUCT_ID">
<generator class="native"/>
</id>