Answer the question
In order to leave comments, you need to log in
Many to many - Hibernate removes the relationship (record in the join table) when updating the entity record. What's wrong?
There is a Many to many relationship - Hibernate removes the relationship (record in the linking table "PRODUCT_ORDER") when updating the record in the entity (in this example it is "PRODUCT") with mapping annotations (meaning @Join table...)
Let's say there is such a database ( test simplified example):
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
;
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 +
'}';
}
}
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 + '\'' +
'}';
}
}
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();
}
}
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";
}
}
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();
}
}
Answer the question
In order to leave comments, you need to log in
I solved the problem like this:
I pulled the object from the session and scored it through setters....
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());
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question