Pergunta

Eu estou procurando uma maneira de obter o Hibernate a função SYS_GUID() uso da Oracle ao inserir novas linhas. Atualmente minhas tabelas de banco de dados tem SYS_GUID() como padrão então se hibernate simplesmente gerado SQL que omitido o valor que ele deve funcionar.

Eu tenho tudo funcionando, mas ele está gerando o UUID / GUID no código usando o gerador UUID do sistema:

@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;
}

Isso é bom, mas eu preferiria que os guids foram geradas pelo banco de dados para que possam ser sequenciais e, potencialmente, ter um melhor desempenho. Além disso, eu gostaria apenas de saber como configurar isso.

Eu estou usando anotações para configuração, mas exemplos de configuração XML são impressionantes também.

Aqui está uma definição da tabela de amostra (no caso importa):

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)
)

UPDATE:

sollution do uso de Mat "guid" trabalhou, aqui está o SQL gerado:

Hibernate: 
    select rawtohex(sys_guid()) 
    from dual
Hibernate: 
    insert into PRODUCT
    (PRODUCT_CODE, PRODUCT_DESC, LOB_ID, PRODUCT_NAME, PROVIDER_ID, PRODUCT_ID) 
    values (?, ?, ?, ?, ?, ?)

Parece que a utilização do valor padrão colunas em uma inserção não for possível, então a escolha é entre um aplicativo gerado guid e uma ida e volta banco de dados.

Foi útil?

Solução

Você pode ser capaz de usar o gerador "guid". Consulte este post do fórum do Hibernate. Parece que eles adicionado suporte para Oracle usando SYS_GUID() um tempo atrás, mas o documentação ainda diz que eles só suportam SQL Server e MySQL.

Eu não tenho trabalhado com anotações JPA ainda, mas aqui está um exemplo usando a configuração XML:

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

EDIT: No que diz respeito à sua segunda pergunta, eu acho que você está perguntando por que o Hibernate não pode fazer algo como isto:

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

A razão é que o Hibernate deve saber o ID do objeto é. Por exemplo, considere o seguinte cenário:

  1. Você cria um novo objeto de Produto e salvá-lo. A Oracle atribui o ID.
  2. Você separar o Produto da sessão do Hibernate.
  3. Você depois anexá-lo novamente e fazer algumas alterações.
  4. Você agora quer persistem essas mudanças.

Sem saber o ID, o Hibernate não pode fazer isso. Ele precisa da ID, a fim de emitir a declaração UPDATE. Assim, a implementação de org.hibernate.id.GUIDGenerator tem para gerar o ID de antemão, e, posteriormente, re-usá-lo na instrução INSERT.

Esta é a mesma razão por que o Hibernate não pode fazer qualquer lotes se você usar um ID gerado pelo banco de dados (incluindo auto-incremento em bancos de dados que a suportam). Usando um dos geradores hilo, ou algum outro mecanismo ID Hibernate gerado, é a única maneira de obter um bom desempenho ao inserir lotes de objetos de uma vez.

Outras dicas

Tenho mesma tarefa que tópico arranque. Com agradecimentos a @ Matt Solnit sugestão que eu usar tais anotações:

@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" e tipo String são partes essenciais da solução.

Antes persistindo novas entidades Hibernate consulta questão SQL:

select rawtohex(sys_guid()) from dual

Minha configuração: Oracle 11, Hibernate 4.3.4.Final, 3.2.x. Primavera E no campo é raw(16) na tabela para o armazenamento eficiente e tamanho do índice menor, em seguida, se você usar char(32).

Quando tento uso java.util.UUID como tipo de campo ID eu recebo erro do Hibernate em persistindo nova entidade (que tentar tipo conjunto String de campo java.util.UUID).

Também eu uso javax.xml.bind.DatatypeConverter para consultas não-Hibernate (ajudantes Primavera JDBC), para passar convertido ao 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);

para extrair:

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

Todos os controladores de web obter códigos como:

025131763FB19522E050010A106D11E9

sem {, -, caracteres } (representação usual de UUID é {a-b-c-d-x-y} se você se lembrar). Esta representação já URL codificação limpa e segura. Você não precisa implementar PropertyEditor ou Convertor para o tipo String:

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

Compare com tentativa fracassada de uso jaa.util.UUID, onde eu preciso escrever:

@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);
}

Para utilizar:

@PathVariable("id") UUID id,

Eu acho que você pode fazê-lo, definindo o gerador para nativa. Eu não estou realmente certo de como fazê-lo em Hibernate, mas em NHibernate você faria algo como isso na XML:

<id column="PRODUCT_ID">
  <generator class="native"/>
</id>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top