-2

I have two tables

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "car")
public class CarEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    private String name;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "manufacture_id")
    private ManufactureEntity manufactureEntity;
}   

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "manufacture")
public class ManufactureEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

There is already an entry named AUDI in the manufacture table. When I try to create a new record

ManufactureEntity manufactureEntity = new ManufactureEntity();
manufactureEntity.setName("AUDI");
CarEntity car = new CarEntity();
car.setName("a6");
car.setManufactureEntity(manufactureEntity);
carService.create(car);

Then I get an error that such a record already exists

org.postgresql.util.PSQLException: ERROR: Duplicate key value violates the "manufacture_name_key" uniqueness constraint
Details: The key "(name)=(AUDI)" already exists.

It turns out that the call to this function is trying to add a new entry to the manufacture table. How do I make this record be created only if it is not there, and if such a record already exists, then the manufacture_id field was simply assigned the key value from the manufacture table?

  1. When adding a new CarEntity record, how can I specify that its manufacture Entity field will be assigned to an existing record in the manufacture "AUDI" table?
  2. But if there is no "AUDI" entry in the manufacture table, then you need to create it.

Or is it impossible to implement it at the same time? But only one of the points.

Or do I misunderstand the OneToOne annotation? One entry in the car "a6" table corresponds to only one entry in the manufacturer "AUDI" table. Let's move on. One entry in the car "a8" table corresponds to only one entry in the manufacturer "AUDI" table. Or am I wrong? And here it is necessary to implement ManyToOne.

If I change the OneToOne annotation to ManyToOne, I get the same error

The key "(name)=(AUDI)" already exists.

If I change CascadeType

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)

adding to the car table works, but adding to the manufacture table does not work if there is no such record there. I.e. when I specify a specific manufacturer

manufactureEntity.setId(1L);

then writing to the car table occurs without errors. But if I specify an unknown manufacturer

manufacture Entity.setName("AUDIM");

Then I get the error

NULL value in the "manufacture_id" column

With the CascadeType.ALL annotation, it works only if there is no such record in the manufacture table and does not work if there is one. With the CascadeType.MERGE annotation, it works only if there is such an entry in the manufacture table and does not work if there is none.

The question remains open. How do I make an entry in the car table and an entry in the manufacture table work? Or is it simply not possible and I need to manually check the existing records in the manufacture table first and if it is not there, then add it, and then write to the car table?

alex
  • 324
  • 1
  • 8
  • 28

1 Answers1

1

It seems that your problem is related to trying to add a new name of "AUDI" to the column of name. Since this column contains the property of unique, you can only have one of "AUDI" in the whole column, which means that even if the id changes, it is not possible to add a new "AUDI" value.

If you still want to be able to add the same values to the column of name (which seems like you want to do), you can do so by removing the column from the table and adding a new column without the unique constraint. Or simply remove the constraint from the table.

Remove uniqueness of index in PostgreSQL

Kypps
  • 326
  • 2
  • 5
  • The field in the manufacturer table must be unique. I don't understand how do I correctly add an entry to the car table? There should be only one AUDI entry in the manufacturer table – alex Jan 27 '22 at 15:47
  • Even though the manufacturer table has a unique name (there can only be one AUDI), in the car table you can have more than one AUDI. So, keep the uniqueness in the manufacturer table but remove the unique constraint in the car table. This way, you can have multiple cars from the same manufacturer (AUDI) – Kypps Jan 27 '22 at 16:05
  • But I don't have a uniqueness constraint on the manufacture_id field in the car table. The error occurs due to the creation of another record in the manufacture table – alex Jan 27 '22 at 16:17
  • Then I think your relationship is not supposed to be OneToOne. When using OneToOne relationship, it means that for every record there can only be ONE record that goes to the column in the other table. Therefore, you cannot have two rows of Manufacturer. Try using ManyToOne (Many cars to one manufacturer) and see if it works – Kypps Jan 27 '22 at 16:30
  • Wait. Why do you think I'm breaking this rule? One entry in the car "a6" table corresponds to only one entry in the manufacturer "AUDI" table. Let's move on. One entry in the car "a8" table corresponds to only one entry in the manufacturer "AUDI" table. Or am I wrong? And here it is necessary to implement ManyToOne. – alex Jan 27 '22 at 16:37
  • I'm not completely sure as I'm also new to this. What you want is to have one manufacturer and have multiple cars of the same manufacturer. The relationship Many to One will not cause your cars to have multiple manufacturers but instead, those manufacturers can (if you want) have access to multiple cars. To understand it better, if you think of Manufacturer to Car it's One to Many (one manufacturer for many cars), so Car to Manufacturer is Many to One (many cars to one manufacturer). – Kypps Jan 27 '22 at 16:43
  • If it worked, I'll edit my answer and you can mark it as the correct answer so others can see. – Kypps Jan 27 '22 at 16:54