4

我有两个实体类 A 和 B,如下所示。

public class A{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;    

    @OneToMany(mappedBy = "a", fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
    private List<B> blist = new ArrayList<B>();

    //Other class members;

}

B类:

public class B{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne
    private A a;

    //Other class members;

}

我有一个将 B 对象添加到 A 对象的方法。我想返回新添加的 B 对象的 id。

例如:

public Long addBtoA(long aID){

            EntityTransaction tx = myDAO.getEntityManagerTransaction();

            tx.begin();
            A aObject = myDAO.load(aID);
            tx.commit();

            B bObject = new B();

            bObject.addB(bObject);

            tx.begin();
            myDAO.save(aObject);
            tx.commit();

            //Here I want to return the ID of the saved bObject.
            // After saving  aObject it's list of B objects has the newly added bObject with it's id. 
            // What is the best way to get its id?


}
4

4 回答 4

4

我不认为接受的答案是正确的。见https://coderanch.com/t/628230/framework/Spring-Data-obtain-id-added

tldr; 您应该为孩子创建一个存储库,B这样您就可以完全独立于其父母来保存孩子。保存B entity后,将其关联到其父级A

这是一些Todo作为父母和Comment孩子的示例代码。

@Entity
public class Todo {

    @OneToMany(mappedBy = "todo", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private Set<Comment> comments = new HashSet<>();

    // getters/setters omitted.
}

@Entity
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "todo_id")
    private Todo todo;

    // getters/setters omitted.
}

如果这是在 spring 数据中建模的,则创建 2 个存储库。TodoRepositoryCommentRepository哪些Autowired在。

给定一个能够接收 POST/api/todos/1/comments以将新评论与给定 todo id 关联的 rest 端点。

    @PostMapping(value = "/api/todos/{todoId}/comments")
    public ResponseEntity<Resource<Comment>> comments(@PathVariable("todoId") Long todoId,
                                                      @RequestBody Comment comment) {

        Todo todo = todoRepository.findOne(todoId);

        // SAVE the comment first so its filled with the id from the DB.
        Comment savedComment = commentRepository.save(comment);

        // Associate the saved comment to the parent Todo.
        todo.addComment(savedComment);

        // Will update the comment with todo id FK.
        todoRepository.save(todo);

        // return payload...
    }

相反,如果您执行了以下操作并保存了提供的参数comment。获得新评论的唯一方法是遍历todo.getComments()并找到提供的comment内容,如果集合是Set.

  @PostMapping(value = "/api/todos/{todoId}/comments")
    public ResponseEntity<Resource<Comment>> comments(@PathVariable("todoId") Long todoId,
                                                      @RequestBody Comment comment) {

        Todo todo = todoRepository.findOne(todoId);

        // Associate the supplied comment to the parent Todo.
        todo.addComment(comment);

        // Save the todo which will cascade the save into the child 
        // Comment table providing cascade on the parent is set 
        // to persist or all etc.
        Todo savedTodo = todoRepository.save(todo);

        // You cant do comment.getId
        // Hibernate creates a copy of comment and persists it or something.
        // The only way to get the new id is iterate through 
        // todo.getComments() and find the matching comment which is 
        // impractical especially if the collection is a set. 

        // return payload...
    }
于 2017-09-28T12:21:35.717 回答
1

您应该首先保留新创建的对象,然后将其添加到其容器中。此外,该save方法org.hibernate.Session返回一个新持久化对象的标识符。所以你只需要更新你的代码和/或你的 DAO 就可以像这样:

newObject.setContainer(container); // facultative (only if the underlying SGBD forbids null references to the container)
Long id = (Long) hibernateSession.save(newObject); // assuming your identifier is a Long
container.add(newObject);
// now, id contains the id of your new object

无论如何,对于所有具有生成 id 的对象,您总是可以执行以下操作:

hibernateSession.persist(object); // persist returns void...
return object.getId(); // ... but you should have a getId method anyway
于 2010-08-09T11:25:28.217 回答
1

我有一个将 B 对象添加到 A 对象的方法。我想返回新添加的 B 对象的 id。

那就去做吧!在新的 B 实例被持久化(并将更改刷新到数据库)之后,它id已经被分配,只需返回它。这是说明此行为的测试方法:

@Test
public void test_Add_B_To_A() {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("MyPu");
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();

    A a = em.find(A.class, 1L);

    B b = new B();
    A.addToBs(b); // convenient method that manages the bidirectional association

    em.getTransaction().commit(); // pending changes are flushed

    em.close();
    emf.close();

    assertNotNull(b.getId());
}

顺便说一句,你的代码有点乱,你不需要commit在每次与 EM 交互之后。

于 2010-08-09T13:31:18.760 回答
0

如果有人在以前的评论中找不到解决方案,另一种选择是添加

@GeneratedValue(strategy = yourChosenStrategy)

通过您正在持久化的实体的 ID(或通过它的 getter)。在这种情况下,当调用persist时,id会自动设置在持久化对象中。

希望能帮助到你 !

于 2013-07-19T09:46:06.730 回答