Question

Let's say I have to fire a query like this:

Select primarykey, columnname, old_value, new_value from first_audit_log;

Select primarykey, columnname, old_value, new_value from second_audit_log;

Select primarykey, columnname, old_value, new_value from third_audit_log; ...so on

audit_log is not mapped as JPA enity to any class and I strictly can't create n number of classes for n number of *_audit_logs.

Using native query feature, how best I can map this to a generic class? Trying to SELECT NEW feature, but not sure... Hence any help is appreciated.

Was it helpful?

Solution

Since your audit logs tables share the same columns, you can create a view that "unifies" those tables and map a single Java class to that view. I believe you can, since you don't need to write updates, I guess.

As an alternative, using native queries would be a good choice.

EDIT:

1) If your audit logs are already views, you can create a view based on other views, if you don't want to create a mapping Java class for each of them. Just remember to add a dummy column that has value 1 if the row comes from the "first" audit log, 2 if it comes from the second, and so on, so you can set them apart.

2) In order to use native queries, assuming your persistence provider is Hibernate, you can do like in this example:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
EntityManager em = emf.createEntityManager();

Session sess = em.unwrap(Session.class); // <-- Use Hibernate-specific features
SQLQuery query = sess.createSQLQuery(
   "SELECT AVG(age) AS averageAge, AVG(salary) as averageSalary FROM persons");

query.setResultTransformer(Transformers.aliasToBean(MyResult.class));
MyResult result = (MyResult) query.list().get(0);

where MyResult is declared as follows:

public class MyResult {

    private BigDecimal averageAge;
    private BigDecimal averageSalary;

    public BigDecimal getAverageAge() {
        return averageAge;
    }
    public void setAverageAge(BigDecimal averageAge) {
        this.averageAge = averageAge;
    }
    public BigDecimal getAverageSalary() {
        return averageSalary;
    }
    public void setAverageSalary(BigDecimal averageSalary) {
        this.averageSalary = averageSalary;
    }

}

and the persons table is like this (MySQL syntax):

CREATE TABLE `persons` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(255) NOT NULL,
  `lastname` varchar(255) NOT NULL,
  `age` int(11) NOT NULL,
  `salary` int(11) NOT NULL,
  PRIMARY KEY (`id`)
);

You can easily adapt this example to your needs, just replace persons and MyResult with what you want.

OTHER TIPS

The aliases in the sql query is automatically converted to upper case and its looking for the setter in Upper case as a result org.hibernate.PropertyNotFoundException Exception is thrown. Any suggestions would be greatly appreciated.

For instance, the below statement is looking for the setter ID instead of Id/id (Could not find setter for ID on class Data)

List<Data> result = entityManager.unwrap(Session.class) 
            .createSQLQuery("Select id as id from table") 
            .setParameter("day", date.getDayOfMonth()) 
            .setParameter("month", date.getMonthOfYear()) 
            .setParameter("year", date.getYear()) 
           .setResultTransformer(Transformers.aliasToBean(Data.class))
           .list();

class Data {
  Integer id;

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
   this.id = id;
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top