Frage

Ich habe zwei Entitätsklassen A und B, die sieht wie folgt aus.

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;

}

Klasse B:

public class B{

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

    @ManyToOne
    private A a;

    //Other class members;

}

habe ich ein Verfahren, das ein B-Objekt zu einem A-Objekt hinzufügt. Ich möchte die ID des neu hinzugefügten B-Objekt zurückzugeben.

Beispiel:

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?


}
War es hilfreich?

Lösung

  

habe ich ein Verfahren, das ein B-Objekt zu einem A-Objekt hinzufügt. Ich möchte die ID des neu hinzugefügten B-Objekt zurückzugeben.

Dann tun Sie es einfach! Nachdem die neue B-Instanz (und die geänderten gespült in die Datenbank) beibehalten wurde, seine id zugewiesen wurde, schicken Sie es einfach. Hier ist ein Testverfahren, das dieses Verhalten veranschaulicht:

@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());
}

übrigens, Ihr Code ist ein bisschen chaotisch, Sie zu commit nach jeder Interaktion mit der EM nicht benötigen.

Andere Tipps

Ich glaube nicht, die akzeptierte Antwort richtig ist. Siehe https://coderanch.com/t/628230/framework / Frühjahr-Data-obtain-id-added

TLDR; Sie sollten nur ein Repository für das Kind B erstellen, so dass Sie das Kind von seinen Eltern völlig unabhängig speichern. Sobald Sie das gespeicherte B entity dann verbinden sie an ihre Mutter A haben.

Hier ist ein Beispielcode mit Todo wobei die Eltern und Comment ist das Kind.

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

Wenn diese im Frühjahr Daten modelliert wurden, erstellen Sie zwei Repositories. TodoRepository und CommentRepository welche Autowired in.

ein Rest Endpunkt empfangen kann POST /api/todos/1/comments Gegeben einen Kommentar mit einer gegebenen todo ID zugeordnet werden soll.

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

Wenn Sie stattdessen haben Sie die unten ein und rettete den mitgelieferten Parameter comment. Der einzige Weg, um den neuen Kommentar zu erhalten ist, durchläuft todo.getComments() und das mitgelieferte comment finden, die imo lästig und unpraktisch ist, wenn die Sammlung ein Set ist.

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

Sie sollten zunächst die neu erstellte Objekt bestehen bleiben, fügen Sie es dann in seinen Behälter. Additionaly, kehrt die Methode der save org.hibernate.Session den Identifikator eines neu anhielt Objekts. So dass Sie nur Ihren Code und / oder Ihre DAO aktualisieren müssen, so verhalten:

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

Wie auch immer, für alle Objekt mit generierten IDs, kann man immer etwas tun:

hibernateSession.persist(object); // persist returns void...
return object.getId(); // ... but you should have a getId method anyway

Falls jemand keine Lösung auf früheren Kommentare finden, eine weitere Option hinzuzufügen

@GeneratedValue(strategy = yourChosenStrategy)

über die ID der Entität, die Sie (oder über die seine Getter) sind persistierende. In diesem Fall, wenn persist aufgerufen wird, wird die ID automatisch in dem persistenten Objekt eingestellt werden.

Hope, es hilft!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top