1. Mapeamento de herança
A herança é um recurso importante orientado a objetos. Ele implementa o uso do código e também possui um relacionamento de herança no modelo de relacionamento. Esse relacionamento de herança pode realmente ser considerado um relacionamento de enumeração. Muitos subtipos podem ser enumerados em um tipo. Esses subtipos formam uma relação de herança com o objeto pai. A maioria das enumerações que podem ser enumeradas pode ser considerada como um mapa de herança. Portanto, essa relação de enumeração pode ser considerada como um mapa de herança. Por exemplo, os animais são uma classe abstrata, que é a classe pai de outros animais, porcos, gatos, etc., e eles são uma relação de herança, como mostra a figura abaixo:
Esse mapeamento de herança gerará uma tabela depois de ser convertida em um modelo relacional. Então, como essa tabela distingue entre esses dois tipos? Use campos relacionais, você precisa adicionar campos de tipo à tabela e usar palavras -chave para indicar o tipo de objeto. Portanto, a estrutura da tabela correspondente ao modelo de objeto na figura acima é a seguinte:
Ao gerar a estrutura da tabela, você precisa adicionar o tipo de campo correspondente, para adicionar o discriminador de mapa correspondente ao arquivo de mapeamento. Aqui você precisa usar o atributo discriminador-valor.
1. Arquivos de classe
Não há necessidade de prestar atenção nos arquivos da classe, basta preste atenção à relação de herança entre eles ao escrever.
Listagem: Código da classe Animal, você só precisa adicionar propriedades básicas.
pacote com.src.hibernate; classe pública Animal {// ID Número privado Int ID; public int getId () {return id; } public void setId (int id) {this.id = id; } // Nome do nome da string privada; public String getName () {Return Name; } public void setName (nome da string) {this.name = name; } // sexo booleano privado de gênero; public boolean issex () {return Sex; } public void setSex (sexo booleano) {this.sex = sexo; }}Listagem 2: Classes de pássaros e porcos, adicionar propriedades básicas e herdar classes de animais.
pacote com.src.hibernate; A classe pública Bird estende Animal {// Height Private int Hight; public int getHeight () {altura de retorno; } public void sethight (int alting) {this.Height = altura; }} pacote com.src.hibernate; classe pública Pig estende o animal {// Peso Private Int Weight; public int getWeight () {Return Weight; } public void setweight (int weight) {this.weight = peso; }} 2. Arquivos de mapa
O mapeamento correspondente precisa ser adicionado ao arquivo de mapeamento. Apenas um arquivo de mapeamento precisa ser adicionado ao modelo, porque apenas uma tabela é gerada, o mapeamento de subclasse correspondente é adicionado ao arquivo de mapeamento. Use a tag <Subclass> e o valor do discriminador é adicionado à tag. Esta propriedade discriminadora indica que tipo é escrito ao escrever dados no banco de dados, como segue:
<? xml versão = "1.0"?> <! Doctype hibernate-mapping public "-// Hibernate/hibernate mapeamento dtd 3.0 // pt" "http://hibernate.sourceforge.net/hibernate tabela = "t_animal"> <id name = "id"> <generator // id> <!-Adicione uma etiqueta de autenticação e deve ser colocado após o id-> <discriminador column = "type"/> <names name = "name"/> <name "sexo" type = "boolean"/> <subclass ("" com.src.ern.ernmate " name = "Weight"/> </subclass> <Subclasse name = "com.src.hibernate.bird" discriminator-value = "b"> <names name = "altura"/> </subclass> </class> </hibernate-mapping> 3. Resultados da análise
A tabela de banco de dados MySQL gerada não apenas adicionará os atributos básicos do animal, mas também adicionará as propriedades de porco e pássaro. Como os atributos adicionados são gravados usando <Subclass> no arquivo de mapeamento, e os atributos discriminadores correspondentes também são adicionados, portanto, as colunas discriminadoras correspondentes serão adicionadas ao banco de dados. A estrutura de tabela gerada é a seguinte:
2. Operação de dados
1. Escreva dados
Ao executar operações de leitura e escrita de dados, você precisa prestar atenção ao uso de operações na classe.
public void testSave () {sessão session = null; tente {// Criar sessão do objeto sessão = hibernateUtils.getSession (); // Abra a transação session.BegIntransaction (); Porco de porco = novo porco (); Pig.setName ("Little Pig"); Pig.SetSex (true); Pig.setWeight (200); session.Save (porco); Pássaro pássaro = novo pássaro (); Bird.setName ("Xiaoniao"); Bird.SetSex (True); Bird.SethEight (100); session.Save (pássaro); session.gettransaction (). Commit (); } catch (Exceção e) {e.printStackTrace (); session.gettransaction (). rollback (); } finalmente {hibernateutils.closhessession (sessão); }}2. Consulta polimórfica e HQL
O método de consulta básica requer apenas o uso de métodos de carga e GET. Aqui nos concentramos na consulta polimórfica. Consulta polimórfica significa que o hibernato pode usar a instância para identificar seu verdadeiro tipo de objeto ao carregar um objeto, para que ele possa ser uma consulta polimórfica.
Nota: As consultas polimórficas não suportam carregamento preguiçoso, ou seja, se você usar o método de carga, precisará definir o carregamento preguiçoso como falso no arquivo de mapeamento.
3. Carregamento de atraso de carga
A carga suporta carregamento preguiçoso. Ao carregar objetos, ele realmente gera o proxy do objeto. Portanto, ao usar consultas polimórficas, você precisa definir o carregamento preguiçoso como falso no arquivo de mapeamento, como segue:
<? xml versão = "1.0"?> <! Doctype hibernate-mapping public "-// Hibernate/hibernate mapeamento dtd 3.0 // pt" "http://hibernate.sourceforge.net/hibernate tabela = "t_animal" lazy = "false"> <id name = "id"> <generator // id> <!-Adicione uma tag de autenticação e deve ser colocado após o id-> <discriminador column = "type"/> <names name = "name"/> <names = "sexo" type = "boolean"/> <subclass = "comcllass"/> <names = "sexo" " <Propriedade name = "Weight"/> </subclass> <Subclasse name = "com.src.hibernate.bird" discriminator-value = "b"> <names name = "altura"/> </subclass> </class> </hibernate-mapping>
Método de carga de carga, usando carregamento para carregar, este exemplo suporta consultas polimórficas e defina o carregamento atrasado como false no arquivo de configuração, para que o método de carga possa ser usado aqui para carregar e obter a classe de objeto correspondente.
public void testLoad () {sessão session = null; tente {session = hibernateUtils.getSession (); session.BegIntransaction (); Animal ani = (animal) session.load (animal.class, 1); System.out.println (ani.getName ()); // Como a carga suporta preguiçosa por padrão, vemos o proxy do animal // para que a instância não possa identificar o verdadeiro tipo Pig //, portanto, a carga não suporta uma consulta polimórfica nesse caso se (ANI Instuly of Pig) {System.out.println ("Eu sou um porco!"); } else {System.out.println ("Eu não sou um porco!"); } session.gettransaction (). Commit (); } catch (Exceção e) {e.printStackTrace (); session.gettransaction (). rollback (); } finalmente {hibernateutils.closhessession (sessão); }} 4.HQL Consulta
O HQL suporta consultas polimórficas, que ocorre principalmente porque a consulta é um objeto real e não retorna um proxy. Portanto, o HQL suporta consultas polimórficas. Além disso, ao consultar, você precisa prestar atenção em não usar nomes de tabela na declaração de consulta, mas usando nomes de classe. Hibernate o mapeará para o nome da tabela correspondente de acordo com o nome da classe, como segue:
public void testLoad5 () {sessão session = null; tente {session = hibernateUtils.getSession (); session.BegIntransaction (); List <Arnalal> list = session.CreateQuery ("From Animal"). List (); for (iterator iter = list.iterator (); iter.hasnext ();) {animal a = (animal) iter.next (); if (uma instância de porco) {System.out.println ("Eu sou um porco!"); } else {System.out.println ("Eu não sou um porco!"); }} session.gettransaction (). Commit (); } catch (Exceção e) {e.printStackTrace (); session.gettransaction (). rollback (); } finalmente {hibernateutils.closhessession (sessão); }}Resultados da consulta:
Hibernato: selecione Animal0_.id como id0_, animal0_.name como nome0_, animal0_.sex como sexo 0_, animal0_.weight como peso0_, animal0_.Height como altura0_, animal0_.Type como tipo0_ de t_animal animal0_ eu sou um piglet! Eu não sou um porco! Eu sou um leitão! Eu não sou um porco!
3. Três estratégias para mapeamento de herança
1. Tabela por hierarquia de classe
Suponha que tenhamos o pagamento da interface e suas várias classes de implementação: CreditcardPayment, CashPayment e ChequePayment. Em seguida, o código de mapeamento da "tabela por hierarquia de classe" é o seguinte:
<class name="Payment" table="PAYMENT"> <id name="id" type="long" column="PAYMENT_ID"> <generator/> </id> <discriminator column="PAYMENT_TYPE" type="string"/> <property name="amount" column="AMOUNT"/> ... <subclass name="CreditCardPayment" discriminator-value="CREDIT"> <property name="creditCardType" Column = "CCTYPE"/> ... </subclass> <Nome da subclasse = "CashPayment" discriminator-value = "Cash"> ... </subclass> <Nome da subclasse = "ChequePayment" discriminador-value = "check"> ... </subclass> </s class>
Apenas uma tabela é necessária para adotar essa estratégia. Ele tem uma grande limitação: exige que os campos definidos por subclasses, como o CCTYPE, não possam ter restrições não nulas.
2. Uma tabela por subclasse
Para as classes no exemplo acima, a estratégia de mapeamento de "uma tabela por subclasse" é adotada e o código é o seguinte:
<classe name = "pagamento" tabela = "pagamento"> <id name = "id" type = "long" column = "paging_id"> <generator/> </id> <propriedades name = "valor" column = "valor"/> ... <kened-subclass name = "creditcardPayment" = "credit_payment"> <kcon_id = " name = "CashPayment" table = "Cash_payment"> <key column = "pag Pays_id"/> <names name = "creditcardtype" column = "cctype"/> ... </junho-subclass> <Key-Subclass name = "Chequepay" tabela "" Cheque>
Quatro tabelas são necessárias. As três tabelas de subclasse estão associadas à tabela de superclasse através de chaves primárias (portanto, o modelo de relacionamento é na verdade associação individual).
3. Cada subclasse possui uma tabela (tabela por subclasse) e use o discriminador
Observe que, para a estratégia de mapeamento de "uma tabela por subclasse", a implementação do hibernato não requer campos discriminadores, enquanto outras ferramentas de mapeamento de objeto/relacional usam um método de implementação diferente do hibernato, que requer uma coluna de discriminador de tipo na tabela de superclasse. O método adotado pelo Hibernate é mais difícil de implementar, mas da perspectiva dos relacionamentos (bancos de dados), é mais correto. Se você estiver disposto a usar a estratégia "uma tabela por subclasse" com campos de discernimento, poderá usar <Subclass> com <ining> da seguinte forma:
<class name="Payment" table="PAYMENT"> <id name="id" type="long" column="PAYMENT_ID"> <generator/> </id> <discriminator column="PAYMENT_TYPE" type="string"/> <property name="amount" column="AMOUNT"/> ... <subclass name="CreditCardPayment" discriminator-value="CREDIT"> <join table="CREDIT_PAYMENT"> <Nome da propriedade = "CreditcardType" column = "cctype"/> ... </ning> </subclass> <Subclasse name = "CashPayment" discriminator-value = "Cash"> <junção tabela = "Cash_Payment"> ... discriminador </junção> </Subclass> <"Nome de Subclass =" ChequaPayment "> discriminação" fetch = "Select"> ... </ingt> </subclass> </s class> </s class>
A declaração opcional fetch = "Select" é usada para dizer a Hibernate que, ao consultar superclasses, não use uma junção externa para pegar os dados da subclasse ChequePayment.