How to retrieve audited register with relationship

2020-06-23 09:40发布

问题:

I´m doubt about using Hibernate Envers and my class.

I have a class Loja.

@Entity
@Audited
@GenericGenerator(name = "Sequence_Generic", strategy = "com.paradigma.ecred.dao.hibernate.generator.ManualGenerator") // sequence generic criado para a atividade 510
@SelectBeforeUpdate @DynamicUpdate
public class Loja extends Persistent {

    @Trim
    @NotBlank(message = "O preenchimento do campo \"CNPJ\" é obrigatório.") 
    @CNPJ(message = "O \"CNPJ da loja\" é inválido")
    private String cnpj;

    @Trim
    @NotBlank(message = "O preenchimento do campo \"Razão social\" é obrigatório.")
    @Size(max = 255, message = "A Razão social deve conter no máximo {max} caracteres.")
    private String razaoSocial;

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="idlojamaster", referencedColumnName = "id", columnDefinition="integer")   
    private Loja lojaMaster;

    @ManyToOne
    @JoinColumn(name="idseguradora", referencedColumnName = "id", columnDefinition="integer")   
    private Seguradora seguradora;

    @ManyToOne
    @JoinColumn(name="idTabelaSeguro", referencedColumnName = "id", columnDefinition="integer") 
    private TabelaSeguro tabelaSeguro;

    // getter e setter
}

I want to know to audit the fields lojaMaster, seguradora, tabelaSeguro. These classes are marked with @Audited. When I make a operation like insert or edit, the Id values area stored in the loja_aud table. But when I retrive these values to shoe in the form I got this message when debugging in Eclipse com.sun.jdi.InvocationException.

It executes the sql by Hibernate, but the class are still null, also I found one method inside these classes, handler. It contains the id of my object.

I´m trying to find informations but it´s very dificult.

So someone can help me!

回答1:

I found one way to deal with my problem that can be yours.

I was debugin my code, and found inside in these entities lojaMaster, seguradora and tabelaSeguro one method called handler. My problem is, the system is been developed in a older database. So Envers would not find these entities in their aud table, and didn´t find.

In this picture you can see, the handler is a proxy object and has the id of the object.

So I started to try to find a way to get this Id. So when I understand this is a proxy object I found in Google the solution Hibernate, and Hibernate make this like a strategy to no get all content of the object.

So I got the code, and got the id.

public Serializable getIdentifier(Object object) {

    if (!(object instanceof HibernateProxy) || Hibernate.isInitialized(object)) {
        return ((Persistent)object).getId();
    }

    HibernateProxy proxy = (HibernateProxy) object;
    LazyInitializer initializer = proxy.getHibernateLazyInitializer();
    return initializer.getIdentifier();
}

So I got and check if my entity Id is null. I got the id, and findById the object. I created one hashmap to don´t every time access the database because ids can repeat.

So these methods were in this way

@Override
public List<Pojo> getLog(Pojo pojo) {

    Map<Long, Loja> mapLoja = new HashMap<>();
    Map<Long, Seguradora> mapSeguradora = new HashMap<>();
    Map<Long, TabelaSeguro> mapTabelaSeguro = new HashMap<>();

    List<Pojo> auditedList = super.getLog(pojo);

    if (!NullUtil.isNull(auditedList)) {

        for (Pojo pojoAudited : auditedList) {

            Long id = null;

            if (NullUtil.isNull(pojoAudited.getLojaMaster().getId())) {

                id = (Long) this.getIdentifier(pojoAudited.getLojaMaster());
                this.getLojaRegister(mapLoja, id);
                pojoAudited.setLojaMaster(mapLoja.get(id));
            }

            if (NullUtil.isNull(pojoAudited.getSeguradora().getId())) {

                id = (Long) this.getIdentifier(pojoAudited.getSeguradora());
                this.getSeguradoraRegister(mapSeguradora, id);
                pojoAudited.setSeguradora(mapSeguradora.get(id));
            }

            if (NullUtil.isNull(pojoAudited.getTabelaSeguro().getId())) {

                id = (Long) this.getIdentifier(pojoAudited.getTabelaSeguro());
                this.getTabelaSeguroRegister(mapTabelaSeguro, id);
                pojoAudited.setTabelaSeguro(mapTabelaSeguro.get(id));
            }

        }
    }

    return auditedList;
}

private void getLojaRegister(Map<Long, Loja> mapLoja, Long id) {

    if (!mapLoja.containsKey(id)) {
        Loja loja = this.findById(id);
        mapLoja.put(id, loja);
    }
}

private void getSeguradoraRegister(Map<Long, Seguradora> mapSeguradora, Long id) {

    if (!mapSeguradora.containsKey(id)) {
        Seguradora seguradora = this.getSeguradoraService().findById(id);
        mapSeguradora.put(id, seguradora);
    }
}

private void getTabelaSeguroRegister(Map<Long, TabelaSeguro> mapTabelaSeguro, Long id) {

    if (!mapTabelaSeguro.containsKey(id)) {
        TabelaSeguro tabelaSeguro = this.getTabelaSeguroService().findById(id);
        mapTabelaSeguro.put(id, tabelaSeguro);
    }
}

I hope this can help someone with problem about Envers and older database.



回答2:

I have the same issue, and in my case was that I started audit on a filled db. When I use an empty db all works fine. I take the info from this