#java #postgresql #hibernate #spring-boot #jpa
#java #postgresql #впасть в спящий режим #пружинный ботинок #jpa
Вопрос:
Повторяющееся значение ключа нарушает ограничение уникальности после сохранения объекта @ManyToOne
Я попытался сохранить объект A, у которого есть другой объект B с уникальным именем поля с помощью spring-data. Если B уже существует в БД, то будет выдано исключение «дублирующее значение ключа нарушает уникальное ограничение «b_name_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:
Это нормально. Поскольку a
объект является новым, операция сохранения будет каскадно передана 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);
Комментарии:
1. Почему спящий режим не может справиться с этим сам?