Unicode de Cordas em consultas do Hibernate
-
22-07-2019 - |
Pergunta
Em um SQL pode escrever uma consulta que procura por um nome de uma pessoa como esta:
SELECT * FROM Person P WHERE P.Name LIKE N'%ike%'
Essa consulta seria executado com caracteres Unicode (assumindo que a coluna Nome e banco de dados foram configuração para suporte alça unicode).
Eu tenho uma consulta similar em HQL que é executado pelo Hibernate (NHibernate). Os olhares de consulta gerados como:
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%カタカ%' )
Infelizmente, colocando um 'N' na frente do literal nos resultados HQL em erro. Eu tentei escapar os caracteres Unicode na seqüência e ainda sem sucesso.
O banco de dados está aceitando e salvar caracteres unicode de Hibernate. Eu tenho sido capaz de preencher com sucesso um objeto com uma string unicode, salve-o com Hibernate e verificá-lo no banco de dados. Parece-me como um pouco estranho que eu não posso usar strings unicode em consultas personalizadas (ou Eu também estou assumindo consultas nomeadas).
Este é um problema ou limitação de Hibernate (Nhibernate) conhecido? Como você usa unicode em HQL?
Vários sites sugerem usando as consultas Critérios. Devido a restrições no quadro que eu estou trabalhando, isso não é possível.
Solução
Você já tentou com parâmetros:
IList<Person> people = session
.CreateQuery("from Person p where p.Name like :name")
.SetParameter("name", "%カタカ%")
.List<Person>();
Eles também têm a vantagem de proteger sua consulta contra injeção de SQL.
Outras dicas
Eu encontrei uma solução que funciona. Eu duvido que ele é a melhor solução. No entanto, é a solução que eu estou indo para implementar até que eu possa autorizar uma reescrita de toda a secção edifício de consulta do software que eu estou trabalhando.
No exemplo:
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%カタカ%')
A cláusula where contém esse literal:
'%カタカ%'
Este literal pode ser dividido em nchars que Hibernate (Nhibernate) vai inconscientemente passar para o SQL que gera. Estranho, mas funciona. Assim, a consulta anterior poderia ser escrito como:
SELECT P FROM SumTotal.TP.Models.Party.Person P join P.Demographics PD WHERE (PD.LastName LIKE '%' + nchar(0x30AB) + nchar(0x30BF) + nchar(0x30AB)+ '%')
Esta solução está longe de ser ideal porque exigiria passando por cada personagem e determinar se era um caractere de vários bytes. No entanto, no caso de que este código vive em seu aplicativo é usado em um gerador de consulta dinâmica que processos múltiplos critérios diferentes em diferentes operações. No exemplo eu dar-lhe está à procura de qualquer lugar unicode na seqüência. É possível que esta função pode ser retornando a parte onde cláusula para uma coluna correspondente a um valor numérico específico ou pode ser procurando os caracteres a partir de uma cadeia de caracteres. O método que constrói o operador usa um tipo de operador eo prazo para devolver uma corda. Eu poderia reescrever isso, mas seria uma tarefa grande. A correção acima me permite processar uma cadeia transmitida para este método. Eu ofereço esta solução porque ela não funciona, mas a resposta de darin é provavelmente a melhor maneira que pude encontrar.
Este problema surge porque NHibernate tenta acessar a coluna sem o comprimento tipo. Daí na hbm.xml é muito importante mencionar comprimento para Legado bancos de dados caso contrário ele irá falhar por Unicode coisas relacionadas.
Obrigado, Thani