【问题标题】:jpa non managed entitiesjpa 非托管实体
【发布时间】:2013-02-20 04:45:16
【问题描述】:

假设我必须触发这样的查询:

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 没有作为 JPA 实体映射到任何类,我严格不能为n 的*_audit_logs 的数量创建n 的类数量。

使用本机查询功能,我如何才能最好地将其映射到泛型类?尝试选择新功能,但不确定...因此感谢您的帮助。

【问题讨论】:

标签: java jpa orm audit-logging


【解决方案1】:

由于您的审计日志表共享相同的列,您可以创建一个“统一”这些表的视图并将单个 Java 类映射到该视图。我相信你可以,因为我猜你不需要编写更新。

作为替代方案,使用本机查询将是一个不错的选择。

编辑:

1) 如果您的审计日志是已经视图,如果您不想为每个视图创建映射 Java 类,则可以基于其他视图创建视图。只要记住添加一个虚拟列,如果该行来自“第一个”审核日志,则其值为 1,如果该行来自第二个审核日志,则添加值为 2,依此类推,这样您就可以将它们分开。

2) 为了使用原生查询,假设你的持久化提供者是 Hibernate,你可以像这个例子中那样做:

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);

其中MyResult 声明如下:

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;
    }

}

persons 表是这样的(MySQL 语法):

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`)
);

您可以根据需要轻松调整此示例,只需将 persons 和 MyResult 替换为您想要的即可。

【讨论】:

  • no ..auditlogs 已经是视图...如何使用本机查询映射到通用类?...我想避免使用 Object[] 路径
  • 您的第二个选项更好,但需要知道如何映射自定义类
  • 您为什么不尝试映射到您的自定义类之一?文档没有说必须管理“resultClass”。
  • 我错了。我更新了我的答案:这似乎是使用 Hibernate 的唯一方法。
【解决方案2】:

sql 查询中的别名会自动转换为大写,并且它会以大写查找 setter,结果会抛出 org.hibernate.PropertyNotFoundException 异常。任何建议将不胜感激。

例如,下面的语句正在寻找 setter ID 而不是 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;
  }
}

【讨论】:

  • 使用 "" 强制区分大小写对我有用...我在以下链接中找到了答案 stackoverflow.com/questions/8136225/…
  • 我还有一个问题,在这行之后会话会发生什么: entityManager.unwrap(Session.class) ?会话会自动关闭还是我们必须明确关闭会话?
猜你喜欢
  • 2011-11-18
  • 2013-11-13
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
相关资源
最近更新 更多