如何在Hibernate中保存一个实体和一个嵌套实体,当两者都有id时?

polhcujo  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(145)

我们在项目中使用的是旧的Hibernate(版本3.6.10),不幸的是,目前还不能升级。
我正在尝试保存实体**,其分配的id**具有以下结构:
我有一个包含id字段的Base类。请注意generator-class="assigned"

public abstract class Base {

    private Long id;

    // contructor

    /**
     * @hibernate.id generator-class="assigned" unsaved-value="null"
     */
    public Long getId() {
        return id;
    }

    // setter
}

然后我有一个类Nested

public class Nested extends Base {

    private Main main;

    // constructor

    /**
     * @hibernate.many-to-one column="main_id" not-null="true" fetch="join"
     * lazy="false" cascade="all"
     * class="Main"
     */
    public Main getMain() {
        return main;
    }
    
    // setter
}

Main类:

public class Main extends Base {

    private List<Nested> nested;

    /**
     * @hibernate.bag cascade="all-delete-orphan" inverse="true" batch-size="10" lazy="false"
     * @hibernate.key column="main_id" on-delete="cascade"
     * @hibernate.one-to-many class="Nested"
     */
    public List<Nested> getNested() {
        return nested;
    }
    // setter
}

当我用一个嵌套对象列表(它们都有id)构造Main对象并尝试保存它(getHibernateTemplate().save(main))时,我在生成的SQL查询中看到:
insert into main...
然后
update nested ...我假设这是因为嵌套记录已经有id了。
如何让Hibernate为Nested示例插入记录?
我知道我可以分别保存每个实体,但我宁愿避免这样做。

qyyhg6bp

qyyhg6bp1#

如果不想单独保存每个Nested实体,可以使用自定义拦截器来修改Hibernate保存实体的行为。
下面是一个示例实现,可以用于相同的
1.实现一个扩展org.hibernate.EmptyInterceptor的自定义拦截器

import org.hibernate.EmptyInterceptor;

public class CustomSaveInterceptor extends EmptyInterceptor {

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        if (entity instanceof Main) {
            Main main = (Main) entity;
            for (Nested nested : main.getNested()) {
                getSession().save(nested); // Manually save each nested entity
            }
        }
        return super.onSave(entity, id, state, propertyNames, types);
    }
}

1.在Hibernate配置中配置自定义拦截器

SessionFactory sessionFactory = configuration.buildSessionFactory(
    new CustomSaveInterceptor()); // Pass your interceptor instance here

1.使用已配置的SessionFactory保存实体

Main main = new Main();
// Set properties for the Main object

Nested nested1 = new Nested();
// Set properties for the Nested object 1

Nested nested2 = new Nested();
// Set properties for the Nested object 2

main.getNested().add(nested1);
main.getNested().add(nested2);

sessionFactory.getCurrentSession().save(main); // Trigger saving with the interceptor

这种方法涉及使用自定义拦截器拦截Main实体的保存过程。保存主实体时,拦截器将在继续保存主实体的正常过程之前手动保存每个关联的嵌套实体。
P.S.:这个解决方案会影响Hibernate会话的全局行为。与往常一样,请确保彻底测试更改,以确保它在您的特定用例中正确工作。

相关问题