2016-07-09 5 views
0

Es gibt zwei Entitäten:
1. Status (zwei Spalten: statusId-Status)
z. Werte: 1 ACTIVE, 2 INACTIVE usw.)
2. Coupon (drei Spalten: couponId title statusId)
z.B. Werte: 10 Orangen 1, 20 Äpfel 2, etc.)JPA-Entity-Beziehung zum Verweisen auf den Wert, aber zum Aktualisieren der referenzierten Entität

Versuchen, herauszufinden, welche Beziehung verwendet werden soll und wie. Ich habe OneToOne, OneToMany, ManyToOne, ManyToMany usw. ausprobiert, aber jedes Mal, wenn die Status-Entität eine neue Zeile erhält, wird
z.B. 21 ACTIVE, 22 ACTIVE, 23 Active usw.

Die Coupon-Entität sollte jedes Mal, wenn ein neuer Coupon gespeichert wird, eine neue Zeile erhalten und den Primärschlüssel des Status im Status-ID-Feld verwenden, aber die Statusentität sollte einen neuen erhalten Zeile hinzugefügt.

Yes, Many coupons can share the same status. 
The following code produces the following results 

Before execution 

Status Table 
StatusId STATUS 
1   ACTIVE 
2   INACTIVE 

Coupon Table 
CouponId Title STATUS 
<no rows at present> 


After execution 

Status Table 
StatusId STATUS 
1   ACTIVE 
2   INACTIVE 
3   ACTIVE (This row should not get inserted) 

Coupon Table 
CouponId  Title StatusId 
10   Apples 3  (StatusId should be 1 instead of 3) 




JSON Request: 

{ 
    "title": "Apples", 
    "status": "ACTIVE", 
} 

Code: 

@Autowired 
CouponRespository couponRepository; 

@RequestMapping(value = "/coupon", method = RequestMethod.POST) 
void createCoupon(@RequestBody Coupon coupon) { 
     couponRepository.save(coupon); 
} 

public interface CouponRespository extends JpaRepository<Coupon, Long> { 

} 

@Entity 
public class Status implements Serializable { 

    @Id 
    @SequenceGenerator(name = "STATUS_STATUSID_GENERATOR", sequenceName = "STATUS_ID_SEQ") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "STATUS_STATUSID_GENERATOR") 
    @Column(name = "STATUS_ID") 
    private long statusId; 

    @Column(name = "STATUS") 
    private String status; 
} 


@Entity 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "couponId") 
@JsonIgnoreProperties({ "statusId" }) 
public class Coupon implements Serializable { 

    @Id 
    @SequenceGenerator(name = "COUPON_COUPONID_GENERATOR", sequenceName = "COUPON_ID_SEQ") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "COUPON_COUPONID_GENERATOR") 
    @Column(name = "COUPON_ID") 
    private long couponId; 

    @Column(name = "TITLE") 
    private String title; 

    @Column(name = "STATUS_ID") 
    private Long statusId; 

    // Need help here how to set this up properly 
    @ManyToOne(cascade = { CascadeType.ALL }) 
    @JoinColumn(name = "STATUS_ID", insertable = false, updatable = false) 
    private Status status; 

} 

Jede Hilfe wird geschätzt.

+0

Können also viele Gutscheine den gleichen Status haben oder nicht? Wenn ja, dann ist es ein ManyToOne, ansonsten ist es ein OneToOne.Geben Sie den Code ein, den Sie zum Erstellen und Speichern eines Gutscheins verwendet haben, teilen Sie ihm mit, was er erwartet und was er stattdessen tut. –

+0

@JBNizet Der Code wurde hinzugefügt, was erwartet wird und was in der Datenbank aktualisiert wird – David

Antwort

1

Ich habe keine Ahnung, wie Jackson möglicherweise eine Coupon-Instanz erstellen kann, die eine Status-Instanz aus dem JSON in Ihrer Frage enthält, und noch weniger, wie eine neue Zeile in der Datenbank erscheinen könnte, da das Statusfeld von COupon nicht eingefügt werden kann. aber wie auch immer, nehme an, es tut das Äquivalent der folgenden Möglichkeiten:

Coupon coupon = new Coupon(); 
coupon.setTitle("Apples"); 
Status status = new Status("ACTIVE"); 
coupon.setStatus(status); 

Sie verlangen, dass Coupon JPA zu speichern. Und Sie haben der JPA gesagt, dass sie die fortbestehende Operation auf den im Coupon enthaltenen Status kaskadieren soll. Der Status hat keine ID. Was kann JPA anderes tun, als ein neues zu erstellen? Wie könnte es sein, dass Sie tatsächlich wollen, dass der neue Coupon mit dem bereits bestehenden Status, der durch die ID 1 identifiziert wird, verknüpft wird? Es kann nicht. Es tut, was du sagst.

Also, was sollten Sie tun?

Entfernen Sie zunächst das Feld StatusId aus Coupon. Dies ist die ID des Status und Sie haben den Status im Gutschein, daher sind diese Informationen redundant.

Zweitens soll der Coupon mit einem bestehenden Status verknüpft werden. So erhalten Sie einen Hinweis auf diese bestehenden Status, und stellen Sie ihn in den Gutschein vor den Gutschein sparen

// this should execute a query that retrieves the Status entity 
// that has the "ACTIVE" status 
Status status = statusRepository.findStatusByStatus("ACTIVE"); 

coupon.setStatus(status); 
couponRepository.save(coupon); 

Drittens: da Sie nicht zwei Status mit dem gleichen Status in der Datenbank wollen, fügen Sie eine eindeutige Einschränkung zu Der Tisch.

Viertens: Da Sie den Status beim Speichern, Ändern oder Löschen eines Gutscheins, der auf diesen Status verweist, nicht speichern, ändern oder löschen möchten, entfernen Sie cascade = { CascadeType.ALL }.

Fünftens: Da die Änderungen an coupon.status dauerhaft sein sollen, entfernen Sie insertable = false, updatable = false.

Sechstens: seit dem, was Sie als JSON in Ihrem Controller erhalten, hat nicht die Struktur eines Coupons, und ist keine Coupon-Instanz, sondern ein Titel und ein Statustext, mit dem Sie den Status mit diesem Text finden und erstellen können eine Coupon-Instanz, erstellen Sie eine Klasse CouponCommandDTO, die die gleiche Struktur wie Ihr JSON hat, und machen Sie den Typ des Parameters Ihres Controllers. Dann wandeln Sie diesen DTO mit dem oben gezeigten Code in einen tatsächlichen Coupon um.

+0

Danke für Ihre Antwort. Abgesehen von der Grundfrage gab es einige zusätzliche Fragen, die mir nicht klar waren, aber Ihre ausführliche Erklärung beantwortete alle meine Fragen. Ich habe die von dir erwähnte Lösung ausprobiert und es hat funktioniert. Das einzige, was ich nicht getan habe, war, CouponCommandDTO zu erstellen, ich habe die status_id als transient gemacht und diesen Wert verwendet, um das Statusobjekt zu erhalten. Danke noch einmal. Es löste nicht nur das Problem, sondern löste auch viele andere Zweifel, die mich beunruhigten. – David