Повторяющееся значение ключа нарушает уникальное ограничение "b_name_key" после сохранения сущности @ManyToOne с помощью Spring-boot, Spring-data, Hibernate - PullRequest
0 голосов
/ 13 апреля 2019

Дублирующее значение ключа нарушает уникальное ограничение после сохранения сущности @ManyToOne

Я попытался сохранить сущность A, у которой есть другая сущность B с уникальным именем поля по данным Spring. Если B уже существует в БД, то будет выдано исключение «дублирующее значение ключа нарушает уникальное ограничение« b_name_key ». Подробно: Key (b_name) = (someName) уже существует.

create table b
(
  b_id         serial primary key,
  b_name varchar(3) not null unique
);

create table a
(
  a_id            serial primary key,
  b_id      int references b (b_id) not null,
);


@Entity
@Getter
@Setter
public class B implements java.io.Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long b_id;
    @Column(name = "b_name", unique = true)
    private String bName;

    public B(String bName) {
        this.bName = bName;
    }

    public B() {}

    @Override
    public String toString() {
        return "...";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        B b = (B) o;
        return Objects.equals(bName, b.bName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(bName);
    }
}

@Entity
@Getter
@Setter
public class a implements java.io.Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long a_id;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "b_id")
    private B b;


    public a() {
    }

    public a(B b  ) {
        this.b = b;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        a a = (a) o;
        return Objects.equals(b, a.b)
    }

    @Override
    public int hashCode() {
        return Objects.hash(b);
    }
}


@Repository
public interface ARepository extends JpaRepository<Metastasis, Long> {}

@Controller
public class AController {

    private final ARepository aRepository;

    public AController(ARepository aRepository) {
        this.aRepository = aRepository;
    }

    @GetMapping("/test")
    public String showaddUserForm() {
        B b = new B("SomeName");
        A a = new A(b);
        aRepository.save(a);
        return "index";
    }
}

@SpringBootApplication
@EnableJpaRepositories(basePackages = "...repositories")
@EnableTransactionManagement
@EntityScan(basePackages = "....entities")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Я получаю org.postgresql.util.PSQLException: ОШИБКА: двойное значение ключа нарушает уникальное ограничение "b_name_key" Подробно: ключ (b_name) = (SomeName) уже существует.

1 Ответ

1 голос
/ 13 апреля 2019

Это нормально. Поскольку объект a является новым, операция PERSIST будет каскадно добавлена ​​к объекту b, который также является новым и завершится неудачно, поскольку в базе данных уже есть запись с этим ключом.

Попробуйте что-то вроде:

// find for B
B b = bRepository.findById(..);
// if not found, create one
if (b == null) {
   b = new B("SomeName");
} 
A a = new A(b);
aRepository.save(a);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...