ANDREW_TUR
@ANDREW_TUR

Many to many — Hibernate удаляет связь (запись в связующей таблице) при обновлении записи сущности. Что не так?

Есть связь Many to many - Hibernate удаляет связь (запись в связующей таблице "PRODUCT_ORDER") при обновлении записи в сущности(в даном примере это "PRODUCT") с анотациями мапинга(имееться ввиду @Join table...)

Допустим есть такая БД(тестовый упрощенный пример):
Код MySql
CREATE DATABASE IF NOT EXISTS `WEBSHOP` DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;
USE `WEBSHOP`;

CREATE TABLE `PRODUCT` (
  `ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `NAME` VARCHAR(255),
  `DESCRIPTION` VARCHAR(255),
  `PRICE` INT(11),
  PRIMARY KEY (`ID`)
)
  COLLATE='UTF8_GENERAL_CI'
  ENGINE=INNODB
;
CREATE TABLE `ORDER` (
  `ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `START_ADRESS` VARCHAR(255),
  `END_ADRESS` VARCHAR(255),
  PRIMARY KEY (`ID`)
)
  COLLATE='UTF8_GENERAL_CI'
  ENGINE=INNODB
;
CREATE TABLE `PRODUCT_ORDER` (
  `PRODUCT_ID` BIGINT(20) NOT NULL,
  `ORDER_ID` BIGINT(20) NOT NULL,
  PRIMARY KEY (`PRODUCT_ID`, `ORDER_ID`),
  CONSTRAINT `FK_PRODUCT` FOREIGN KEY (`PRODUCT_ID`) REFERENCES `PRODUCT` (`ID`),
  CONSTRAINT `FK_ORDER` FOREIGN KEY (`ORDER_ID`) REFERENCES `ORDER` (`ID`)
)
  COLLATE='UTF8_GENERAL_CI'
  ENGINE=INNODB
;


В коде есть две сущности:
Код первой. Product - При обновлении записи этой и удаляеться связь- запись с связующей таблице `PRODUCT_ORDER`
package com.blackside.group.entity;

import org.hibernate.annotations.*;

import javax.persistence.*;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "`PRODUCT`")
public class Product implements Serializable {

	private static final long serialVersionUID = 1919474471074343742L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "`ID`", nullable = false)
	private long id;

	@Column(name = "`NAME`")
	private String name;

	@Column(name = "`DESCRIPTION`")
	private String description;

	@Column(name = "`PRICE`")
	private int price;

	@ManyToMany(fetch = FetchType.LAZY, cascade = javax.persistence.CascadeType.ALL)
	@JoinTable(name = "`PRODUCT_ORDER`",
			joinColumns = {@JoinColumn(name = "`PRODUCT_ID`")},
			inverseJoinColumns = {@JoinColumn(name = "`ORDER_ID`")})
	private Set<Order> orders = new HashSet<Order>();

	public Product() {
	}

	public Product(String name, String description, int price) {
		this.name = name;
		this.description = description;
		this.price = price;
	}

	public long getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public String getDescription() {
		return description;
	}

	public int getPrice() {
		return price;
	}

	public Set<Order> getOrders() {
		return orders;
	}

	public void setId(long id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}

	@Override
	public String toString() {
		return "Product{" +
				"id=" + id +
				", name='" + name + '\'' +
				", description='" + description + '\'' +
				", price=" + price +
				'}';
	}
}


И вторая:
Код второй. Order
package com.blackside.group.entity;
@Entity
@Table(name = "`ORDER`")
public class Order implements Serializable {

	private static final long serialVersionUID = 5031143999897706901L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "`ID`", nullable = false)
	private long id;

	@Column(name = "`START_ADRESS`")
	private String startAdress;

	@Column(name = "`END_ADRESS`")
	private String endAdress;


@ManyToMany(cascade = javax.persistence.CascadeType.ALL, mappedBy = "orders")
	private Set<Product> products = new HashSet<Product>();

	public Order() {
	}

	public Order(String startAdress, String endAdress) {
		this.startAdress = startAdress;
		this.endAdress = endAdress;
	}

	public long getId() {
		return id;
	}

	public String getStartAdress() {
		return startAdress;
	}

	public String getEndAdress() {
		return endAdress;
	}

	public Set<Product> getProducts() {
		return products;
	}


	public void setId(long id) {
		this.id = id;
	}

	public void setStartAdress(String startAdress) {
		this.startAdress = startAdress;
	}

	public void setEndAdress(String endAdress) {
		this.endAdress = endAdress;
	}

	public void setProducts(Set<Product> products) {
		this.products = products;
	}

	@Override
	public String toString() {
		return "Order{" +
				"id=" + id +
				", startAdress='" + startAdress + '\'' +
				", endAdress='" + endAdress + '\'' +
				'}';
	}
}
Вопрос: что я упустил? Где ошибся?

Если это поможет то вот
Структура:
Нажмите чтоб развернуть
da506e47338a49d7beaa04c0c08add5b.jpg

Код HibernateConfig:
Нажмите чтоб развернуть
package com.blackside.group.config;

@Configuration
@EnableTransactionManagement
@PropertySource(value = {"classpath:application.properties"})
@ComponentScan({"com.blackside.group"})
public class HibernateConfig {


  @Autowired
  private Environment environment;

  @Bean(name = "dataSource")
  public DriverManagerDataSource getDataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
    dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
    dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
    dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
    return dataSource;
  }

  @Bean
  public Properties getHibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.use_sql_comments", environment.getRequiredProperty("hibernate.use_sql_comments"));
    properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
    properties.put("hibernate.id.new_generator_mappings", environment.getRequiredProperty("hibernate.id.new_generator_mappings"));
    properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
    return properties;
  }

  @Bean
  public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(getDataSource());
    sessionFactory.setPackagesToScan(new String[] { "com.blackside.group.entity" });
    sessionFactory.setHibernateProperties(getHibernateProperties());
    return sessionFactory;
  }

  @Bean
  @Autowired
  public HibernateTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
    return new HibernateTransactionManager(sessionFactory);
  }

  @Bean
  public ProductDAO getProductDAO() {
    return new ProductDAOImpl();
  }
  @Bean
  public OrderDAO getOrderDAO() {
    return new OrderDAOImpl();
  }


}


Код ProductController:
Нажмите чтоб развернуть
package com.blackside.group.controller;

@Controller
public class ProductController {

	@Autowired
	@Qualifier("productService")
	private ProductService productService;

	@RequestMapping(value = "/product", method = RequestMethod.GET)
	public String getListProduct(ModelMap model) {
		List<Product> productList = productService.getAll();
		model.addAttribute("productList", productList);
		return "product";
	}

	@RequestMapping(value = "/product/new", method = RequestMethod.GET)
	public String addProduct(ModelMap model) {
		model.addAttribute("action", "Add new");

		Product product = new Product();
		model.addAttribute("product", product);

		return "productCreate";
	}

	@RequestMapping(value = { "/product/new" }, method = RequestMethod.POST)
	public String saveProduct(Product product) {

		productService.add(product);
		return "redirect:/product";
	}

	@RequestMapping(value = { "/product/delete/{idProduct}" }, method = RequestMethod.GET)
	public String deleteProduct(@PathVariable long idProduct) {
		productService.delete(idProduct);
		return "redirect:/product";
	}

	@RequestMapping(value = {  "/product/edit/{idProduct}" }, method = RequestMethod.GET)
	public String editProduct(@PathVariable long idProduct, ModelMap model) {
		model.addAttribute("action", "Edit");

		Product product = productService.get(idProduct);
		model.addAttribute("product", product);
		model.addAttribute("edit", true);
		return "productForm";
	}

	@RequestMapping(value = {  "/product/edit/{idProduct}" }, method = RequestMethod.POST)
	public String updateProduct(Product product) {
		productService.update(product);
		return "redirect:/product";
	}
}


Код ProductDaoImpl:
Нажмите чтоб развернуть
package com.blackside.group.dao;
@Repository
public class ProductDAOImpl implements ProductDAO {

	@Autowired
	private SessionFactory sessionFactory;

	private Session getCurSes() {
		return sessionFactory.getCurrentSession();
	}

	public void add(Product item) {
		getCurSes().save(item);
	}

	public void update(Product item) {
		getCurSes().merge(item);
	}

	public void delete(long itemId) {
		Product product = get(itemId);
		if (product != null) getCurSes().delete(product);
	}

	public Product get(long itemId) {
		Product product = (Product) getCurSes().get(Product.class, itemId);
		return product;
	}
	public List<Product> getAll() {
		Criteria criteria = getCurSes().createCriteria(Product.class);
		return criteria.list();
	}
}

  • Вопрос задан
  • 531 просмотр
Решения вопроса 1
ANDREW_TUR
@ANDREW_TUR Автор вопроса
Решил задачу так:
Дернул обьект из сессии и забил через сеттеры....
public void update(Order item) {
//			getCurSes().merge(item);

		Order entity = (Order) getCurSes().get(Order.class, item.getId());
		if(entity!=null){
			entity.setStartAdress(item.getStartAdress());
			entity.setEndAdress(item.getEndAdress());
		}
	}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы