Pergunta

Eu tenho uma classe de hibernato que é essencialmente apenas uma embalagem em torno de muitas coleções.

Portanto, a classe é (massivamente simplificada/pseudo) algo como:

@Entity  
public class MyClass {

  @OneToMany  
  Map1

  @OneToMany  
  Map2

  @OneToMany   
  Map3

  AddToMap1();  
  AddToMap2();  
  AddToMap3();  
  RemoveFromMap1();  
  RemoveFromMap2();  
  RemoveFromMap3();  
  DoWhateverWithMap1();  
  DoWhateverWithMap2();  
  DoWhateverWithMap3();  

}

etc. Cada um desses mapas possui alguns métodos associados a ele (adicione/remover/interrogar/etc).

Como você pode imaginar, quando adicionei a 10ª coleção, a classe está ficando um pouco ridícula de tamanho.

O que eu adoraria fazer é algo parecido com:

 
@Entity  
public class MyClass {

  ClassWrappingMap1;

  ClassWrappingMap2;

  ClassWrappingMap3;
}

Com todos os vários métodos envolvidos nessas classes:

public class ClassWrappingMap1 {

  @OneToMany
  Map

  AddToMap();  
  RemoveFromMap();  
  DoWhateverWithMap();  

}

Eu pensei que talvez pudesse usar @Embedded Para isso, mas pareço não conseguir fazê -lo funcionar (o Hibernate simplesmente nem tenta persistir o mapa dentro do WrapperClass).

Alguém já fez algo assim antes? Alguma dica?

Muito Obrigado,
Ned

Foi útil?

Solução

Manual de hibernação para anotações Estados seguintes:

Embora não seja apoiado pela especificação EJB3, as anotações de hibernato permitem usar anotações de associação em um objeto incorporável (ou seja, @*toone nem @*tomany). Para substituir as colunas da associação, você pode usar o @associationOverRide.

Portanto, sua abordagem de embalagem deve funcionar.


Primeiro de tudo, você deve verificar todos os arquivos de log etc para qualquer erro relacionado.

Você poderia tentar algo assim:

  • Em sua aula mestre (myclass)
@Entity  
public class MyClass {

  @Embedded
  ClassWrappingMap1 map1;
}
  • E em sua aula de embrulho
@Embeddable
public class ClassWrappingMap1 {

  @OneToMany
  Map map1;

}

Notar que ClassWrappingMap1 usos @Embeddable anotação. No entanto, de acordo com os documentos, a anotação @embeddable não deve ser necessária, ela deve ser padrão quando a anotação @embedded for usada.

Certifique -se de que toda classe Classwappingmap mapeie uma coluna diferente no banco de dados. Além disso, as classes ClassWrappingMap não devem ter uma chave primária (@Id ou @EmbeddedId colunas).

Outras dicas

Embora eu não conheça uma estratégia padrão ao usar uma classe de wrapper, você pode usar um interceptor de hibernato para inicializar o seu invólucro, substituindo carregando método. Algo como

public class WrapperInterceptor extends EmptyInterceptor {

    private Session session;

    public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        if (entity instanceof MyClass) {
             MyClass myClass = (MyClass) entity;

             Query query = session.createQuery(<QUERY_TO_RETRIEVE_WRAPPED_ENTITY_GOES_HERE>);

             WrappedEntity wrappedEntity = query.list().get(0);

             myClass.setWrapperClass(new WrapperClass(wrappedEntity));
        }
    }

    public void setSession(Session session) {
        this.session = session;
    }
}

Cuida do seguinte:

Um cliente usando este interceptador deve definir a propriedade de sessão

Então seu código se parece com este

WrapperInterceptor interceptor = new WrapperInterceptor();

Session session = sessionFactory().openSession(interceptor);

Transaction tx = session.beginTransaction();

interceptor.setSession(session);

MyClass myClass = (MyClass) session.get(newItem, myClassId); // Triggers onLoad event

tx.commit();
session.close();

Ou use a Spring AOP para realizar a mesma tarefa. Ver Design de domínio com primavera e hibernação

Se você conhece outra estratégia, compartilhe conosco.

Saudações,

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top