Hibernate 5 Bytecode Enhancement Association Management 只在一个方向上工作

Hibernate 5 Bytecode Enhancement Association Management works just in one direction

我有 2 个这样映射的 JPA 实体:

@MappedSuperclass
public class AbstractEntity {

    private static final String INCREMENT_STRATEGY = "increment";

    private static final String INCREMENT_ID_GENERATOR_NAME = "INCREMENT_ID_GENERATOR";
    
    @Id
    @GenericGenerator(name = INCREMENT_ID_GENERATOR_NAME, strategy = INCREMENT_STRATEGY)
    @GeneratedValue(generator = INCREMENT_ID_GENERATOR_NAME)
    private Long id;

    public AbstractEntity() {
        super();
    }
    
    public Long getId() {
        return id;
    }
}

@Entity
public class Department extends AbstractEntity{
    
    
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "department")
    private List<Employee> employees = new ArrayList<Employee>();

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }
    
    public List<Employee> getEmployees() {
        return employees;
    }

}

@Entity
public class Employee extends AbstractEntity {

    @ManyToOne(optional = true, cascade= CascadeType.ALL)
    @JoinColumn(name = "DEPARTMENT_ID")
    private Department department;

    public void setDepartment(Department department) {
        this.department = department;
    }

    public Department getDepartment() {
        return department;
    }

}

所有 类 都是 byte-code 使用 hibernate 增强 maven 插件增强的:

<build>
    <plugins>
        <plugin>
            <groupId>org.hibernate.orm.tooling</groupId>
            <artifactId>hibernate-enhance-maven-plugin</artifactId>
            <version>5.2.2.Final</version>
            <dependencies>
                <dependency>
                    <groupId>org.hibernate</groupId>
                    <artifactId>hibernate-entitymanager</artifactId>
                    <version>5.2.2.Final</version>
                </dependency>
            </dependencies>
            <configuration>
                <enableDirtyTracking>true</enableDirtyTracking>
                <enableLazyInitialization>true</enableLazyInitialization>
                <enableAssociationManagement>true</enableAssociationManagement>
            </configuration>
        </plugin>
    </plugins>
</build>

我 运行 进行了两次测试,以验证增强的 类 是否正常工作:

@Test
public void test1() {
    Department department = new Department();
    Employee employee = new Employee();
    department.getEmployees().add(employee);
    assertThat(employee.getDepartment(), is(not(nullValue())));
}

@Test
public void test2() {
    Department department = new Department();
    Employee employee = new Employee();
    employee.setDepartment(department);
    assertThat(department.getEmployees().size(), is(1));
    assertThat(department.getEmployees().get(0), is(employee));
}

只有第二个测试成功通过,因此当通过 parent 的集合操作关联时,child 的 parent 字段不会更新,而在 Hibernate ORM 5.2.3.Final User Guide 表示

Bytecode-enhanced bi-directional association management makes that first example work by managing the "other side" of a bi-directional association whenever one side is manipulated.

引用的“第一个例子”是

Example 204. Incorrect normal Java usage

为什么在我的 test1 案例中关联管理不起作用?我做错了什么?

在单元测试中,可能会发生 类 没有得到增强的情况,尤其是当您通过 IDE.

运行 它们时

确保增强的 类 包含在您导入到进行测试的项目中的不同模块中。

或者您可以 运行 增强过程,验证 类 是否增强,然后才 运行 单元测试。

总而言之,我猜您可能 运行正在使用实体的未增强版本 类。

总之,我认为这个功能不是很有必要。 Syncing both ends of the associations is the way to go,只需要你提供一个addChild和removeChild方法即可。

追踪 Andrei 的 JIRA 问题我了解到:

to trigger the association management, at some point there has to be a change in the *ToMany field, even if it's with the same collection. The collection itself is not tracked for changes.

所以,而不是:

customer.getInventories().add( customerInventory );

需要调用 setter:

Collection<CustumerInventory> inventories = customer.getInventories();
inventories.add( customerInventory ); 
custumer.setInventories( inventories );