java - 如何让 Hibernate/Spring/JPA 自动更新新实体的 ID

标签 java spring hibernate jpa

我有一个包含子实体的聚合。当我保存聚合时,聚合的 ID 和子实体不会更新。有没有办法让 JPA 实体管理器自动更新 ID,或者是保存和获取返回聚合然后再次找到您刚刚添加的子实体的唯一解决方案?我正在使用 Spring CrudRepositories 来保存我所有的聚合。

我正在使用:

Spring 4.0.3

hibernate 4.3.5

JPA 2.1

这是我的基本代码。

@MappedSuperclass
public class AbstractEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    protected Long id;
}


@Entity
@Table(name = "foo")
public class Foo extends AbstractEntity{
    @OneToMany(cascade=CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "foo")
    private List<Bar> bars;

    public void addBar(Bar bar)
    {
        bar.setBar
        bars.add(bar);
    }
}

@Entity
@Table(name = "bar")
public class Bar extends AbstractEntity{
    @ManyToOne
    @JoinColumn(name = "foo_id", nullable = false)
    private Foo foo;

    protected setFoo(Foo foo){
        this.foo = foo;
    }
}

@Repository
@Transactional(propagation = Propagation.MANDATORY)
interface FooRepository extends CrudRepository<Foo, Long> {
}

@Service
public class DoStuffService()
{
    @AutoInject
    private FooRepository fooRepository;

    public Bar doStuff(long id)
    {
        Foo foo = fooRepository.findOne(id);
        Bar bar = createSomeBar();
        foo.addBar(bar);
        fooRepository.save(foo);
        return bar; // I would like this to have the id filled out from the save of the aggregate rather than having to go to the get the Foo again and go through the collection to find the right bar so I can return it with an ID.
    }
}

@Service
@Transactional
public class SomeRootServiceService()
{
    @AutoInject
    private DoStuffService doStuffService;

    public Bar doRootStuff()
    {
         Bar bar = doStuffService.doStuff(someId);
         if (bar.getId() == null){
             //Should never get here but I do.
         }
    }
}

编辑:添加一些信息来阐明我们的最终目标是什么,id 问题只是一个症状。

我们真正想做的是获取一个从聚合创建的实体,并将其传递给链接到同一数据库事务内的新创建实体的其他东西,并且由于该实体不是然而“保存” hibernate 抛出一个 transient 实体错误。

最佳答案

您可以使用以下代码:

@Id
@Column(name = "id") //Don't need nullable = false as primary keys can never be null
@GeneratedValue(generator = "generatorName")
@SequenceGenerator(name = "generatorName", sequenceName = "SEQ_NAME")
protected Long id;

您可以在您的数据库中自己创建序列,或者如果 Hibernate 正在为您生成您的模式,它会这样做。

Hibernate 将使用这些注释在创建新对象时自动从数据库中获取序列的下一个值,而无需您做任何事情。非常方便。如果您的级联设置正确,您只需保存父对象,然后子对象将被创建并自动分配 ID。

就其值(value)而言,拥有一个仅用于封装 ID 的映射抽象父类(super class)对我来说没有意义。一个对象的 ID 是其个体状态所固有的,每个对象都应该有一个唯一的序列来生成 ID。为什么需要两个对象都使用相同的 ID 源。每个对象都应该有一个唯一的 ID 用于它自己的表。

如果所有子类都共享该功能,并且您的对象都需要 ID,那么您只能将功能封装在父类(super class)中,而这些 ID 彼此不相关。所以你不能说 Foo_ID 与 Bar_ID 相关,它们应该是完全独立的。

另一个不相关的说明,你为什么不在 Spring 中使用 @AutoInject 而不是 @Autowired?

关于第三个不相关的说明,为什么您的 DAO 被注释为 @Transactional。服务层是所有事务管理和对象操作应该发生的地方。如果你需要你的 DAO 注释 @Transactional 你有问题。你也不应该需要那个传播修饰符。 Hibernate 在防止事务相互干扰方面做得非常出色。

关于java - 如何让 Hibernate/Spring/JPA 自动更新新实体的 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23412408/

相关文章:

java - 返回一组已安装的应用程序,不含系统应用程序

java - 使用 MongoOperations 删除 Mongo 上的多个数组条目

spring - 当 Hibernate 在不同的模式上已经可用时,它不会生成 Sequence

java - 带 Spring @Async 注解的方法未执行

java - 字符串数据,右截断 - Hibernate with Spring Boot

hibernate - 什么是 hibernate 中的上下文 session ?

mysql - 集合映射的 where 子句

java - Web 服务 (JAX-WS) 和继承

java - 递归方法给我错误

java - 如何在Java中正确动态地初始化多维数组?