JPA - Entity dopplet inder Datenbank verhindern - UniqueConstraint scheitern aufgrund Vererbung ?

8u3631984

Bekanntes Mitglied
Hallo zusammen.
Was möchte ich :
Ich möchte eine Entity abspeichern. Das klappt auch - kein Problem. Nun möchte ich aber verhindern, dass das Entity doppelt gespeichert wird.dazu habe ich ein UniqueConstraint angelegt. Allerdings greift das nicht. Was ich noch ewähnen muss : Die Felder (Columns) sind in der Parent Klasse enthalten :

Kann mir jemand helfen :
[CODE lang="java" title="Meine Parent Klasse"]
@AllArgsConstructor
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class AbstractCalendarItem extends CalendarEntity implements CalendarItem {

protected LocalDateTime dateTime;
protected String description;
protected String associationName;
protected Integer seasonStartYear;
protected Integer seasonEndYear;
protected String competitionName;
protected CompetitionGender competitionGender;
protected String firstTeamName;
protected String secondTeamName;
protected Integer setPointsFirstTeam = 0;
protected Integer setPointsSecondTeam = 0;[/CODE]

[CODE lang="java" title="Die Klasse möchte ich abspeichern"]@Entity
@Table(name = "samsCalendarItem", uniqueConstraints = @UniqueConstraint(columnNames = {"dateTime", "associationName", "seasonStartYear", "seasonEndYear", "competitionName", "competitionGender", "firstTeamName", "secondTeamName"}))
@ToString(callSuper = true)
public class SamsCalendarItem extends AbstractCalendarItem implements CalendarItem {

@Builder(setterPrefix = "with", toBuilder = true)
public SamsCalendarItem(LocalDateTime dateTime, String description, String associationName, Integer seasonStartYear, Integer seasonEndYear, String competitionName, CompetitionGender competitionGender, String firstTeamName, String secondTeamName, Integer setPointsFirstTeam, Integer setPointsSecondTeam) {
super(dateTime, description, associationName, seasonStartYear, seasonEndYear, competitionName, competitionGender, firstTeamName, secondTeamName, setPointsFirstTeam, setPointsSecondTeam);
}
[/CODE]

[CODE lang="java" title="Hier der Test"] @Autowired
private SamsCalendarItemRepository unitUnderTest;

// Test Data
private SamsCalendarItem firstSamsCalendarItem = TestData.getSamsCalendarItemWithRequiredData();
private SamsCalendarItem secondSamsCalendarItem = TestData.getSamsCalendarItemWithRequiredData();

private SamsCalendarItem firstCompleteSamsCalendarItem = TestData.getSamsCalendarItemWithAllData();
private SamsCalendarItem secondCompleteSamsCalendarItem = TestData.getSamsCalendarItemWithAllData();

@Test
@DisplayName("can not save sams calendar item with same data")
void testCanNotSaveSamsCalendarItemWithSameData() {
assertThat(unitUnderTest.findAll().size()).isZero();

assertThat(firstSamsCalendarItem.getId()).isNull();
firstSamsCalendarItem = unitUnderTest.saveAndFlush(firstSamsCalendarItem);
assertThat(firstSamsCalendarItem.getId()).isNotZero();

assertThat(secondSamsCalendarItem.getId()).isNull();
assertThrows(DataIntegrityViolationException.class, () -> unitUnderTest.save(secondSamsCalendarItem));
assertThat(secondSamsCalendarItem.getId()).isNull();
}[/CODE]

Das Problem ist, dass beim Speichern von der selben Entity keine Exception kommt.
Weiß jemand Rat ?
 

8u3631984

Bekanntes Mitglied
Wo ist denn die @Id-Annotation?
[CODE lang="java" title="Die Parent klasse"]@Data
@MappedSuperclass
public abstract class CalendarEntity {

@Id
@GeneratedValue
private Long id;

@Version
private int version;

@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false)
private Date creationDate = new Date();
}[/CODE]
 

LimDul

Top Contributor
Ich würde als ersten Schritte- anstelle von isNotZero auf isNotNull prüfen. Das interessiert dich mehr als das Zero.
Sprich, wurde das wirklich gespeichert?
Und dann mal debuggen ob wirklich 2 Datensätze in der Datenbank landen
 

8u3631984

Bekanntes Mitglied
Habe das mal umgebaut :
Java:
        assertThat(unitUnderTest.findAll().size()).isZero();

        assertThat(firstSamsCalendarItem.getId()).isNull();
        firstSamsCalendarItem = unitUnderTest.saveAndFlush(firstSamsCalendarItem);
        assertThat(firstSamsCalendarItem.getId()).isNotNull();

        assertThat(secondSamsCalendarItem.getId()).isNull();
        assertThrows(DataIntegrityViolationException.class, () -> unitUnderTest.save(secondSamsCalendarItem));
        assertThat(secondSamsCalendarItem.getId()).isNull();

Gleiches Ergebnis :
Ich habe mir mal die Anzahl und die element aus der Datenbank ausgeben lassen :

[CODE lang="java" title="Test mit Ausgabe"] assertThat(unitUnderTest.findAll().size()).isZero();

assertThat(firstSamsCalendarItem.getId()).isNull();
firstSamsCalendarItem = unitUnderTest.saveAndFlush(firstSamsCalendarItem);
assertThat(firstSamsCalendarItem.getId()).isNotNull();

assertThat(secondSamsCalendarItem.getId()).isNull();
secondSamsCalendarItem = unitUnderTest.saveAndFlush(secondSamsCalendarItem);
// assertThrows(DataIntegrityViolationException.class, () -> unitUnderTest.save(secondSamsCalendarItem));
// assertThat(secondSamsCalendarItem.getId()).isNull();
unitUnderTest.findAll().stream().forEach(calendarItem -> System.out.println(calendarItem) );[/CODE]

Java:
SamsCalendarItem(super=AbstractCalendarItem(super=CalendarEntity(id=1, version=0, creationDate=Fri Sep 10 15:35:30 CEST 2021), dateTime=Optional[2020-07-12T12:30], description=Optional[test-Team-1 vs. test-Team-2], associationName=Optional[test-Association], seasonStartYear=Optional[2020], seasonEndYear=Optional[2021], competitionName=Optional[test-Competition], competitionGender=Optional[MIXED], firstTeamName=Optional[test-Team-1], secondTeamName=Optional[test-Team-2], setPointsFirstTeam=Optional.empty, setPointsSecondTeam=Optional.empty))

SamsCalendarItem(super=AbstractCalendarItem(super=CalendarEntity(id=2, version=0, creationDate=Fri Sep 10 15:35:30 CEST 2021), dateTime=Optional[2020-07-12T12:30], description=Optional[test-Team-1 vs. test-Team-2], associationName=Optional[test-Association], seasonStartYear=Optional[2020], seasonEndYear=Optional[2021], competitionName=Optional[test-Competition], competitionGender=Optional[MIXED], firstTeamName=Optional[test-Team-1], secondTeamName=Optional[test-Team-2], setPointsFirstTeam=Optional.empty, setPointsSecondTeam=Optional.empty))

Kann es damit zu tun haben, dass die Column Felder auf die ich das UniqueConstraint anwende in einer anderen Klasse definiert sind ?
Denn die KLasse SamsCalendarItem erbt ja von AbstractCalendarItem -> hier sind auch alle Felder enthalten
 

8u3631984

Bekanntes Mitglied
Konnte den Fehler feinden :
Mein Parent Class sieht nun so aus :
[CODE lang="java" title="@MappedSuperclass fehlte"]@AllArgsConstructor
@MappedSuperclass
@ToString(callSuper = true)
public abstract class AbstractCalendarItem extends CalendarEntity implements CalendarItem {

[/CODE]
 

Ähnliche Java Themen

Neue Themen


Oben