Hibernate5 update only collection 多对多关系
Hibernate5 update only collection many to many relationship
我用 Hibernate 5.2 映射了下图
这些是我的实体类:
股票
@Entity
@Table(name = "stock", catalog = "mkyongdb", uniqueConstraints = {
@UniqueConstraint(columnNames = "STOCK_NAME"),
@UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "STOCK_ID", unique = true, nullable = false)
private Integer stockId;
@Column(name = "STOCK_CODE", unique = true, nullable = false, length = 10)
private String stockCode;
@Column(name = "STOCK_NAME", unique = true, nullable = false, length = 20)
private String stockName;
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinTable(name = "stock_category", catalog = "mkyongdb", joinColumns = {
@JoinColumn(name = "STOCK_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "CATEGORY_ID",
nullable = false, updatable = false) })
private Set<Category> categories = new HashSet<>();
//Getter and Setter
}
类别
@Entity
@Table(name = "category", catalog = "mkyongdb")
public class Category implements java.io.Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "CATEGORY_ID", unique = true, nullable = false)
private Integer categoryId;
@Column(name = "NAME", nullable = false, length = 10)
private String name;
@Column(name = "[DESC]", nullable = false)
private String desc;
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories", cascade = {CascadeType.MERGE, CascadeType.REFRESH})
private Set<Stock> stocks = new HashSet<>();
//Getter and Setter
}
一切正常。
我需要做的只是为一只股票添加一个类别列表。我不想修改 Stock
实体,只是在 stock_category
table.
中添加或删除类别
这是我的服务:
@Override
@Transactional(rollbackFor = StockException.class)
public void addCategoriesToStock(Set<Category> categories, Stock stock) throws StockException{
stock = sessionFactory.getCurrentSession().get(Stock.class, stock.getCodStock());
stock.setCategories(categories);
sessionFactory.getCurrentSession().update(stock);
sessionFactory.getCurrentSession().flush();
}
这是服务测试
@Test
public void testAddCategoriesStock() throws Exception {
Stock newValues = new Stock();
newValues.setStockId(1);
Category category = new Category();
category.setCategoryId(13);
dao.addCategoriesToStock(new HashSet<>(Arrays.asList(category)), newValues);
List<Stock> stocks = dao.getAllStockeByCategoriesCriteria(category);
for (Stock stock : stocks) {
System.out.println(stock);
}
}
测试运行良好,没有错误,但是在浏览与类别“13”(getAllStockeByCategoriesCriteria
)关联的股票时,它没有给我带来任何股票。然后之前执行的操作没有生效
如何添加或删除类别?
您必须在两侧添加依赖项,因此您缺少将 Stock 添加到 categories
:
@Override
@Transactional(rollbackFor = StockException.class)
public void addCategoriesToStock(List<Category> categories, Stock stock) throws StockException{
stock = sessionFactory.getCurrentSession().get(Stock.class, stock.getCodStock());
stock.setCategories(categories);
for(Category cat: categories){
cat.getStocks().add(stock);
}
sessionFactory.getCurrentSession().merge(stock);
sessionFactory.getCurrentSession().flush();
}
此外,我认为您应该使用 merge
而不是 update
以使级联工作。
之后您的代码应保存关系。
根据第一反应,这是我留在方法中的代码。
更改签名,因为我只需要实体的标识符即可将它们关联起来,并且如 Maciej Kowalski 所示,关系必须保持双向
我还通过 Set 更改了列表,以确保值不会重复
这将是我向关系添加类别列表的服务
@Override
@Transactional(rollbackFor = StockException.class)
public void addCategoriesToStock(Set<Integer> categoryCodes, Integer codStock) throws StockException{
//I get the stock I'm going to associate
Stock stock = sessionFactory.getCurrentSession().get(Stock.class, codStock);
if (categoryCodes != null) {
//For each category to add to the stock, I consult and add the relationship in both entities
for (Integer codCategory : categoryCodes) {
Category category = sessionFactory.getCurrentSession().get(Category.class, codCategory);
category.add(stock);
stock.add(category);
}
}
sessionFactory.getCurrentSession().merge(stock);
sessionFactory.getCurrentSession().flush();
}
这将是从关系中删除类别列表的服务
@Override
@Transactional(rollbackFor = StockException.class)
public void removeCategoriesToStock(Set<Integer> categoryCodes, Integer codStock) throws StockException{
//I get the stock that I will disassociate
Stock stock = sessionFactory.getCurrentSession().get(Stock.class, codStock);
if (categoryCodes != null) {
//For each category to eliminate the stock, I consult and eliminate the relationship in both entities
for (Integer codCategory : categoryCodes) {
Category category = sessionFactory.getCurrentSession().get(Category.class, codCategory);
category.remove(stock);
stock.remove(category);
}
}
sessionFactory.getCurrentSession().merge(stock);
sessionFactory.getCurrentSession().flush();
}
我的疑问是,在建立两个实体之间的关系之前,我必须在数据库中查询它们以获取对象并对其进行操作。因此,我必须为我将关联的每个标识符执行此操作,我想这应该是一个性能问题。
但目前我会留下它,以防我找到更优化的方法post它在这里
我用 Hibernate 5.2 映射了下图
这些是我的实体类:
股票
@Entity
@Table(name = "stock", catalog = "mkyongdb", uniqueConstraints = {
@UniqueConstraint(columnNames = "STOCK_NAME"),
@UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "STOCK_ID", unique = true, nullable = false)
private Integer stockId;
@Column(name = "STOCK_CODE", unique = true, nullable = false, length = 10)
private String stockCode;
@Column(name = "STOCK_NAME", unique = true, nullable = false, length = 20)
private String stockName;
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinTable(name = "stock_category", catalog = "mkyongdb", joinColumns = {
@JoinColumn(name = "STOCK_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "CATEGORY_ID",
nullable = false, updatable = false) })
private Set<Category> categories = new HashSet<>();
//Getter and Setter
}
类别
@Entity
@Table(name = "category", catalog = "mkyongdb")
public class Category implements java.io.Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "CATEGORY_ID", unique = true, nullable = false)
private Integer categoryId;
@Column(name = "NAME", nullable = false, length = 10)
private String name;
@Column(name = "[DESC]", nullable = false)
private String desc;
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories", cascade = {CascadeType.MERGE, CascadeType.REFRESH})
private Set<Stock> stocks = new HashSet<>();
//Getter and Setter
}
一切正常。
我需要做的只是为一只股票添加一个类别列表。我不想修改 Stock
实体,只是在 stock_category
table.
这是我的服务:
@Override
@Transactional(rollbackFor = StockException.class)
public void addCategoriesToStock(Set<Category> categories, Stock stock) throws StockException{
stock = sessionFactory.getCurrentSession().get(Stock.class, stock.getCodStock());
stock.setCategories(categories);
sessionFactory.getCurrentSession().update(stock);
sessionFactory.getCurrentSession().flush();
}
这是服务测试
@Test
public void testAddCategoriesStock() throws Exception {
Stock newValues = new Stock();
newValues.setStockId(1);
Category category = new Category();
category.setCategoryId(13);
dao.addCategoriesToStock(new HashSet<>(Arrays.asList(category)), newValues);
List<Stock> stocks = dao.getAllStockeByCategoriesCriteria(category);
for (Stock stock : stocks) {
System.out.println(stock);
}
}
测试运行良好,没有错误,但是在浏览与类别“13”(getAllStockeByCategoriesCriteria
)关联的股票时,它没有给我带来任何股票。然后之前执行的操作没有生效
如何添加或删除类别?
您必须在两侧添加依赖项,因此您缺少将 Stock 添加到 categories
:
@Override
@Transactional(rollbackFor = StockException.class)
public void addCategoriesToStock(List<Category> categories, Stock stock) throws StockException{
stock = sessionFactory.getCurrentSession().get(Stock.class, stock.getCodStock());
stock.setCategories(categories);
for(Category cat: categories){
cat.getStocks().add(stock);
}
sessionFactory.getCurrentSession().merge(stock);
sessionFactory.getCurrentSession().flush();
}
此外,我认为您应该使用 merge
而不是 update
以使级联工作。
之后您的代码应保存关系。
根据第一反应,这是我留在方法中的代码。
更改签名,因为我只需要实体的标识符即可将它们关联起来,并且如 Maciej Kowalski 所示,关系必须保持双向
我还通过 Set 更改了列表,以确保值不会重复
这将是我向关系添加类别列表的服务
@Override
@Transactional(rollbackFor = StockException.class)
public void addCategoriesToStock(Set<Integer> categoryCodes, Integer codStock) throws StockException{
//I get the stock I'm going to associate
Stock stock = sessionFactory.getCurrentSession().get(Stock.class, codStock);
if (categoryCodes != null) {
//For each category to add to the stock, I consult and add the relationship in both entities
for (Integer codCategory : categoryCodes) {
Category category = sessionFactory.getCurrentSession().get(Category.class, codCategory);
category.add(stock);
stock.add(category);
}
}
sessionFactory.getCurrentSession().merge(stock);
sessionFactory.getCurrentSession().flush();
}
这将是从关系中删除类别列表的服务
@Override
@Transactional(rollbackFor = StockException.class)
public void removeCategoriesToStock(Set<Integer> categoryCodes, Integer codStock) throws StockException{
//I get the stock that I will disassociate
Stock stock = sessionFactory.getCurrentSession().get(Stock.class, codStock);
if (categoryCodes != null) {
//For each category to eliminate the stock, I consult and eliminate the relationship in both entities
for (Integer codCategory : categoryCodes) {
Category category = sessionFactory.getCurrentSession().get(Category.class, codCategory);
category.remove(stock);
stock.remove(category);
}
}
sessionFactory.getCurrentSession().merge(stock);
sessionFactory.getCurrentSession().flush();
}
我的疑问是,在建立两个实体之间的关系之前,我必须在数据库中查询它们以获取对象并对其进行操作。因此,我必须为我将关联的每个标识符执行此操作,我想这应该是一个性能问题。
但目前我会留下它,以防我找到更优化的方法post它在这里