我正在开发一个基本的Spring Boot零售商应用程序,该应用程序可跟踪产品,其制造商以及这些产品所属的类别。类别和产品之间存在多对多关系。当尝试保存添加了新产品的类别时,即使(category_id,product_id)的组合是唯一的,也会出现错误,表明我违反了唯一的主键约束。关于这是为什么以及如何解决的任何想法?
类别
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany
@JoinTable(name="product_categories",
joinColumns = @JoinColumn(name="category_id"),
inverseJoinColumns = @JoinColumn(name="product_id"))
private Set<Product> products;
`<rest of class omitted>`
产品
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private double price;
@ManyToOne
private Manufacturer manufacturer;
@ManyToMany(mappedBy = "products")
private Set<Category> categories;
'<rest of class omitted>'
DevBootstrap
Manufacturer sony = new Manufacturer("Sony");
manufacturerRepository.save(sony);
Category console = new Category("Game Console");
categoryRepository.save(console);
Category robot = new Category("Robot");
categoryRepository.save(robot);
Category electronics = new Category("Electronic Device");
categoryRepository.save(electronics);
Product ps4 = new Product("Playstation 4", 300, sony);
ps4.getCategories().add(electronics);
ps4.getCategories().add(console);
productRepository.save(ps4);
electronics.getProducts().add(ps4);
console.getProducts().add(ps4);
categoryRepository.save(electronics);
categoryRepository.save(console);
sony.getProducts().add(ps4);
manufacturerRepository.save(sony);
Product aibo = new Product("AIBO Robotic Dog", 150, sony);
aibo.getCategories().add(electronics);
aibo.getCategories().add(robot);
productRepository.save(aibo);
electronics.getProducts().add(aibo);
robot.getProducts().add(aibo);
System.out.println("Ids: " + electronics.getId() + ", " + aibo.getId());
categoryRepository.save(electronics); // <- Error occurs here
categoryRepository.save(robot);
sony.getProducts().add(aibo);
manufacturerRepository.save(sony);
错误
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_5 ON PUBLIC.PRODUCT_CATEGORIES(CATEGORY_ID, PRODUCT_ID) VALUES 1"; SQL statement:
insert into product_categories (category_id, product_id) values (?, ?) [23505-199]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:457) ~[h2-1.4.199.jar:1.4.199]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:427) ~[h2-1.4.199.jar:1.4.199]
at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.199.jar:1.4.199]
at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.199.jar:1.4.199]
at org.h2.index.BaseIndex.getDuplicateKeyException(BaseIndex.java:103) ~[h2-1.4.199.jar:1.4.199]
at org.h2.mvstore.db.MVSecondaryIndex.checkUnique(MVSecondaryIndex.java:220) ~[h2-1.4.199.jar:1.4.199]
at org.h2.mvstore.db.MVSecondaryIndex.add(MVSecondaryIndex.java:196) ~[h2-1.4.199.jar:1.4.199]
at org.h2.mvstore.db.MVTable.addRow(MVTable.java:546) ~[h2-1.4.199.jar:1.4.199]
at org.h2.command.dml.Insert.insertRows(Insert.java:180) ~[h2-1.4.199.jar:1.4.199]
at org.h2.command.dml.Insert.update(Insert.java:132) ~[h2-1.4.199.jar:1.4.199]
at org.h2.command.CommandContainer.update(CommandContainer.java:133) ~[h2-1.4.199.jar:1.4.199]
at org.h2.command.Command.executeUpdate(Command.java:267) ~[h2-1.4.199.jar:1.4.199]
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:200) ~[h2-1.4.199.jar:1.4.199]
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:154) ~[h2-1.4.199.jar:1.4.199]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-3.2.0.jar:na]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
... 58 common frames omitted
答案 0 :(得分:0)
您的代码中存在多个问题。
save
。请注意,CrudRepository.save method有一个返回值,文档说:将返回的实例用于进一步的操作,因为保存操作可能已完全更改了实体实例。
您无需在ManyToMany的两侧都调用save来保持关系。一侧就足够了。
您的关系管理绝非习惯。
我强烈建议您向产品添加addCategory
方法,这将在Product.categories和Category.products中添加条目
最好还是重新考虑一下您的映射。对于玩具应用程序来说已经足够好了,但是您真的要拥有Category.products产品集吗?当您的数据库增大时,获取它会破坏性能。