Ebean 中的条件@OnetoMany 关系

Conditional @OnetoMany relationship in Ebean

我有一个 parent 实体,它与 child 实体有 OneToMany 关系。

我想定义它们之间的条件关系,其中 child 有一个值为 3 的 attribute 列字段。attribute 是 [=15 中的整数列=] table 像模型中这样:

@Constraints.Required
@NotNull
protected Integer attribute;

这是我在 parent 实体中尝试的 class:

@OneToMany(mappedBy = "parent")
@Where(clause = "attribute = 3")
List<Child> specificChildren;

然而,生成的查询忽略了我创建的 where 子句,并向我提供了与该父项相关的所有子项,而不仅仅是具有 attribute = 3 的子项。将 clause 更改为 ${ta}.attribute = 3 也不成功。

这里是 SQL 生成的 query.getGeneratedSql():

select distinct on (t1.attribute, t0.id) t0.id, t1.attribute
from parent t0
left join child t1 on t1.parent_id = t0.id
order by t1.someotherattribute

@Where 属性被完全忽略,因为无论我用它做什么,生成的 SQL 都不会受到影响。

有一个 io.ebean.annotation.Where class,所以看起来它应该可以工作,但我还没有找到关于它的任何 Ebean 特定文档(Ebean 的文档似乎有点不足)。我找到的关于 @Where 注释的大部分信息都与 Hibernate 相关。不过我确实找到了它的源代码 here

这种方式支持吗?或者有其他方法可以实现吗?

我目前正在使用 PostgreSQL 10.4、Ebean 10.4.4、Play 2.6.7,使用 Play 的 Ebean 插件 4.0.6。我尝试更新到 Play 的 Ebean 4.1.3 但没有成功。不确定我使用的版本是否是罪魁祸首。

在 Google 组 here 中找到更多信息。

它对我有效,所以请让我:

  1. 先说说我这边的样子
  2. 然后就你这边的问题提供一个假设
  3. 然后问一些澄清问题(以防需要进一步的帮助)

工作解决方案

我使用了 Ebean 10.4.4PostgreSQL 10(适用于 MySQL 6.7 也是)。

  1. 主要部分来自Employeeclass,是一个child实体:

    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
    
    protected int attribute;
    
  2. 主要部分来自部门class,是一个parent实体:

    @OneToMany(mappedBy = "department")
    @Where(clause = "attribute = 3")
    private List<Employee> employees = new ArrayList<Employee>();
    
  3. 查找查询

    Query<Department> query = Ebean.find(Department.class).fetch("employees")
            .where().eq("name", "DevOps").query();
    Department department = query.findUnique();
    String queryString = query.getGeneratedSql();
    System.out.println(queryString);
    

    这里的重要部分是急切地获取 "employees" 字段。结果输出如下所示:

    select t0.id, t0.name, t1.id, t1.name, t1.attribute_test, t1.department_id
    from department t0
    left join employee t1 on t1.department_id = t0.id
    where attribute_test = 3 and t0.name = ?
    order by t0.id
    

假设

主要假设(因为我不知道你是如何 queried/searched 实体的)是你没有急切地获取 child 实体并且它们是使用单独的 SQL.

例如在我上面的示例中,如果我将删除 .fetch("employees") 部分并将这样做:

Query<Department> query = Ebean.find(Department.class)
        .where().eq("name", "DevOps").query();
Department department = query.findUnique();
String queryString = query.getGeneratedSql();
System.out.println(queryString);
System.out.println(department); // uses this.employees in #toString() - so will lazily fetch child entities

我会有:

  • 以下 queryString 的输出:

    select t0.id, t0.name from department t0 where t0.name = ?
    
  • department 的下一个输出(我在部门中有两名员工 attribute = 2 和一名 attribute = 3):

    Department [
      id=1,
      name=java,
      employees=[{Employee [id=3, name=Batman, attribute=3, department=DevOps]}]
    ]
    
  • 和日志中的 2 个 SQL 查询(此处使用 Logback),一个用于查找部门,另一个用于获取员工(使用 @Where相关逻辑):

    08:09:35.038 [main] DEBUG io.ebean.SQL - txn[1001] select t0.id, t0.name from department t0 where t0.name = ? ; --bind(java)
    08:09:35.064 [main] DEBUG io.ebean.SQL - txn[1002] select t0.department_id, t0.id, t0.name, t0.attribute_test, t0.department_id from employee t0 where attribute_test = 3 and (t0.department_id) in (?) ; --bind(1)
    

澄清问题

如果上述方法不起作用,请提供以下信息:

  1. 使用的是哪个版本的 PostgreSQL?

  2. @ManyToOne是用在child实体端吗?

  3. 能否提供您的程序发起的 SQL 查询的日志?

    启用 Logback 就足够了,就像 here >>: just need to add dependencies and to utilize this >> 配置文件中描述的那样。