簡體   English   中英

以一對多關系獲取持久子對象的ID

[英]Getting the ID of the persisted child object in a one-to-many relationship

我有兩個實體類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?


}

我有一個方法,它將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());
}

順便說一句,你的代碼有點亂,你不需要在每次與EM交互后commit

我不認為接受的答案是正確的。 請參閱https://coderanch.com/t/628230/framework/Springwel-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以將新評論與給定的待辦事項ID相關聯。

    @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則該comment很煩人且不切實際。

  @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...
    }

您應該先保留新創建的對象,然后將其添加到其容器中。 另外, org.hibernate.Sessionsave方法返回一個新持久化對象的標識符。 所以你只需更新你的代碼和/或你的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

如果有人在先前的評論中找不到解決方案,則另一個選項是添加

@GeneratedValue(strategy = yourChosenStrategy)

在你持久存在的實體的ID上(或在它的getter上)。 在這種情況下,當調用persist時,id將自動設置在持久化對象中。

希望能幫助到你 !

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM