2017-06-22 9 views
1

Sagen wir, ich habe zwei Objekte, sagen wir, ein Objekt ist ein Benutzer und das andere ist ein State-Objekt. Das Staatsobjekt ist im Grunde die 50 Staaten von Amerika, so dass es sich nicht ändern muss. Das Benutzerobjekt hat jedoch eine Sammlung von Zuständen, in denen der Benutzer war. So wie folgt aus:Ein Objekt aus Objekt A in Objekt B einfügen, ohne ein neues Objekt zu erstellen? HIBERNATE

@Entity 
@Table(name="tbl_users") 
class User { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="id", unique=true, nullable = false) 
    private int id; 

    @Column(name="user_name") 
    private String name; 

    @OneToMany(targetEntity=State.class, orphanRemoval = false) 
    @Column(name="states") 
    private Collection<State> states; 

    //getters and setters 
} 

und die Einheit Staaten sieht wie folgt aus:

@Entity 
@Table(name="tbl_states") 
class State { 

    @Id 
    @Column(name="id", unique=true, nullable=false) 
    private int id; 

    @Column(name="state") 
    private String state; 

    // getters and setters 
} 

-Code für das Hinzufügen von Benutzer (unter Verwendung von Hibernate):

public int addUser(User user) { 
    em.persist(user); 
    em.flush(); 
    return user.getId(); 
} 

-Code für den Zustand von id bekommen:

public State getStateById(int id) { 
    return em.createQuery("SELECT s FROM State s WHERE s.id =:id, State.class) 
      .setParameter("id", id) 
      .getSingleResult(); 
} 

aber wenn ich es versuche ein Benutzer erstellen und mehrere Staaten holen, erhalte ich eine PSQLException:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uk_g6pr701i2pcq7400xrlb0hns" 
2017-06-21T22:54:35.959991+00:00 app[web.1]: Detail: Key (states_id)=(5) already exists. 

Ich habe versucht, die Cascade Methoden suchen, um zu sehen, ob ich verwenden könnte, aber Cascade.MERGE und Cascade.PERSIST scheinen das Gleiche zu tun, und der Rest glaube ich nicht (REMOVE, DETACH, etc). Meine Frage ist: Wie füge ich Zustände zum Benutzerobjekt hinzu, ohne diesen Fehler zu haben?

+0

Wie rufen Sie Ihre Statusobjekte ab, bevor Sie sie Ihrem Benutzerobjekt hinzufügen? –

+0

@AbassA Ich mache eine getStateById() für jedes und es gibt das state-Objekt in eine Array-Liste zurück, und dann füge ich diese Array-Liste mit der Setter-Methode – Aria

+0

dem Benutzer hinzufügen Könnten Sie den vollständigen Code, wo Sie die Speichermethode verarbeiten . Warum haben Sie eine @Column-Funktion über Ihrem Sammelattribut, die Sie nicht benötigen, und ich stelle mir vor, dass Sie eine Tabelle user_state haben, die die Beziehung unterstützt? –

Antwort

1

Dieser Code funktioniert:

class Example { 

    @Test 
    public void workingTest() { 
     EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU"); 
     EntityManager em = emf.createEntityManager(); 

     // Creating three states 
     State alabama = new State(state: 'Alabama'); 
     State louisiana = new State(state: 'Louisiana'); 
     State texas = new State(state: 'Texas'); 
     em.getTransaction().begin(); 
     em.persist(alabama); 
     em.persist(louisiana); 
     em.persist(texas); 
     em.getTransaction().commit(); 

     List<State> states = em.createQuery('FROM State').getResultList(); 

     // Assert only three states on DB 
     assert states.size() == 3; 

     User userFromAlabama = new User(); 
     User userFromAlabamaAndTexas = new User(); 

     em.getTransaction().begin(); 
     State alabamaFromDB = em.find(State, alabama.getId()); 
     State texasFromDB = em.find(State, texas.getId()); 
     userFromAlabama.getStates().add(alabamaFromDB); 
     userFromAlabamaAndTexas.getStates().add(alabamaFromDB); 
     userFromAlabamaAndTexas.getStates().add(texasFromDB); 

     em.persist(userFromAlabama); 
     em.persist(userFromAlabamaAndTexas); 
     em.getTransaction().commit(); 

     states = em.createQuery('FROM State').getResultList(); 

     // Assert only three states on DB again 
     assert states.size() == 3; 

     // Assert one user 
     User userFromDB = em.find(User, userFromAlabama.getId()); 
     assert userFromDB.getStates().size() == 1; 

     userFromDB = em.find(User, userFromAlabamaAndTexas.getId()); 
     assert userFromDB.getStates().size() == 2; 
    } 
} 

@Entity 
@Table(name="tbl_users") 
class User { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id 

    @Column(name="user_name") 
    private String name 

    @ManyToMany 
    private Collection<State> states = Lists.newArrayList() 

    // Getters and setters 
} 

@Entity 
@Table(name="tbl_states") 
class State { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 

    @Column(name="state") 
    private String state; 
    // Getters and setters 
} 

Sie Ihre Mapping ändern sollte @ManyToMany!

Und Sie müssen 3 Tische auf DB wie diese: TBL_USERS, TBL_STATES und TBL_USERS_TBL_STATES

Die TBL_USERS_TBL_STATES Tabelle ist der Standardtabellenname, Hibernate verwendet, wenn eine Eigenschaft mit @ManyToMany bezeichnet ist. Wenn Sie den Tabellennamen von TBL_USERS_TBL_STATES ändern möchten, verwenden Sie auch die Annotation @JoinTable. Siehe Dokumentation here

Mit dieser Konfiguration sollten Sie in der Lage sein, einen Status aus der Datenbank abzurufen, ihn einem neuen Benutzer hinzuzufügen und ihn dann dauerhaft zu speichern. Ich habe einen Unit Test gemacht und es funktioniert!

+0

sagst du zu @OneToMany-Konfiguration zu entfernen? – Aria

+0

Ja, weil Sie es nicht brauchen. Was Sie wirklich brauchen, ist sicherzustellen, dass die Zwischentabelle 'TBL_USERS_TBL_STATES' in Ihrer Datenbank existiert. Hibernate wird diese Tabelle verwenden, um die Zustände eines Benutzers (die Stats-Auflistung) zuzuordnen! – rafaelim

+0

services_id? Wo ist dieses Feld? – rafaelim

0

In Ihrem Fall könnte es besser sein, eine manyTomany-Assoziation mit manyTomany Hibernate zu verwenden, generieren Sie keine Unicity-Constraint.

Hibernate automatische Generierung Schema Verhalten ist ein wenig seltsam mit onetoMany, aber Sie können diese Problemumgehung verwenden.

Versuchen Sie folgendes:

@ManyToMany 
@JoinTable(name = "user_state") 
private List<State> states; 
+0

Dies hat nicht funktioniert, es erstellt mehrere Benutzer auf einmal ? Wie wenn ich 2 Zustände wähle, schafft es 2 Benutzer mit den gleichen Details (ausgenommen ID) – Aria

+0

Es sollte funktionieren, vielleicht ist Ihre Speicherlogik nicht korrekt, fügen Sie bitte in Ihrem Postdetail all Ihres Geschäftscodes hinzu, ich brauche das ganze Bild. von der Benutzerinstanz oder dem Laden, bis der persist und flush zur Datenbank den Code um die adduser-Methode enthielt. –

Verwandte Themen