Spring JPA - A different object with the same identifier value was already - spring

I have 3 classes :
#Entity
public class Purchase {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id ;
private String description ;
private float discount ; //percentage
private boolean status ; // paid or not
#ManyToOne
#JoinColumn(name = "company_id")
#JsonIgnore
private Company company ;
#ManyToOne
#JoinColumn(name = "BusinnesPartner_id")
#JsonIgnore
private BusineesPartner busineesPartner ;
#OneToMany(mappedBy = "purchase", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<PurchaseItem> purchaseItems;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public float getDiscount() {
return discount;
}
public void setDiscount(float discount) {
this.discount = discount;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public BusineesPartner getBusineesPartner() {
return busineesPartner;
}
public void setBusineesPartner(BusineesPartner busineesPartner) {
this.busineesPartner = busineesPartner;
}
public Set<PurchaseItem> getPurchaseItems() {
return purchaseItems;
}
public void setPurchaseItems(Set<PurchaseItem> purchaseItems) {
this.purchaseItems = purchaseItems;
}
public Purchase() {
super();
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
return "Purchase [id=" + id + ", description=" + description + ", discount=" + discount + ", status=" + status
+ ", company=" + company + ", busineesPartner=" + busineesPartner + ", purchaseItems=" + purchaseItems
+ "]";
}
}
And item :
#Entity
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id ;
private String name ;
private String brand ;
private String category ;
private Double unitPrice ;
private Double weight ;
private String manufacturer ;
private String description ;
#ManyToOne
#JoinColumn(name = "company_id")
private Company company ;
#OneToMany(mappedBy = "item")
private Set<ItemInventory> itemInventories;
#OneToMany(mappedBy = "item")
private Set<PurchaseItem> purchaseItems;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public Double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(Double unitPrice) {
this.unitPrice = unitPrice;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<ItemInventory> getItemInventories() {
return itemInventories;
}
public void setItemInventories(Set<ItemInventory> itemInventories) {
this.itemInventories = itemInventories;
}
#Override
public String toString() {
return "Item [id=" + id + "]";
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public Set<PurchaseItem> getPurchaseItems() {
return purchaseItems;
}
public void setPurchaseItem(Set<PurchaseItem> purchaseItems) {
this.purchaseItems = purchaseItems;
}
public Item(Integer id, String name, String brand, String category, Double unitPrice, Double weight,
String manufacturer, String description, Company company, Set<ItemInventory> itemInventories,
Set<PurchaseItem> purchaseItems) {
super();
this.id = id;
this.name = name;
this.brand = brand;
this.category = category;
this.unitPrice = unitPrice;
this.weight = weight;
this.manufacturer = manufacturer;
this.description = description;
this.company = company;
this.itemInventories = itemInventories;
this.purchaseItems = purchaseItems;
}
public Item() {
}
}
And PurchaseItem :
#Entity
#Table(name = "purchase_item")
public class PurchaseItem implements Serializable {
#Id
#ManyToOne
#JoinColumn(name = "item_id")
private Item item ;
#Id
#ManyToOne
#JoinColumn(name = "purchase_id")
private Purchase purchase ;
private Long quantity ;
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public Purchase getPurchase() {
return purchase;
}
public void setPurchase(Purchase purchase) {
this.purchase = purchase;
}
public Long getQuantity() {
return quantity;
}
public void setQuantity(Long quantity) {
this.quantity = quantity;
}
public PurchaseItem(Item item, Purchase purchase, Long quantity) {
super();
this.item = item;
this.purchase = purchase;
this.quantity = quantity;
}
public PurchaseItem() {
super();
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
return "PurchaseItem [item=" + item + ", purchase=" + purchase + ", quantity=" + quantity + "]";
}
}
And here is my controller :
#RestController
public class PurchaseController {
#Autowired
private ItemRepository itemRepos ;
#Autowired
private InventoryRepository inventoryRepos ;
#Autowired
private CompanyRepository companyRepos ;
#Autowired
private PurchaseRepository purchaseRepos ;
#RequestMapping(value = "purchase/add/{company}", method = RequestMethod.POST)
public Object addItem(#RequestBody Purchase purchase) {
Purchase newPurchase = new Purchase() ;
newPurchase.setDiscount(purchase.getDiscount());
newPurchase.setStatus(purchase.isStatus());
newPurchase.setBusineesPartner(purchase.getBusineesPartner()) ;
newPurchase.setDescription(purchase.getDescription()) ;
newPurchase.setPurchaseItems(new HashSet<PurchaseItem>());
newPurchase = purchaseRepos.save(newPurchase) ;
for(PurchaseItem curentPurchaseItem : purchase.getPurchaseItems()) {
Item item = itemRepos.findOne(curentPurchaseItem.getItem().getId()) ;
curentPurchaseItem.setPurchase(newPurchase);
curentPurchaseItem.setItem(item);
newPurchase.getPurchaseItems().add(curentPurchaseItem) ;
}
return purchaseRepos.save(newPurchase) ;
}
}
Here is the error Stack :
A different object with the same identifier value was already
associated with the session :
[com.inconso.models.PurchaseItem#PurchaseItem [item=null,
purchase=null, quantity=25]]; nested exception is
javax.persistence.EntityExistsException: A different object with the
same identifier value was already associated with the session :
[com.inconso.models.PurchaseItem#PurchaseItem [item=null,
purchase=null, quantity=25]]

Related

How can I fetch data from 2 tables using HQL having one to many association with each other?

I have 2 tables in my database, city and hotel_details. Primary key of city is foreign key in hotel_details and associated with one to many association. I want to fetch data(status,registration,etc..) from hotel_details based on city_id and hotel_name by calling getAvailabilityStatus from my controller. Following is my code :
City Entity class
#Entity
#Table(name="city")
public class City {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="city_name")
private String cityName;
#OneToMany(mappedBy="city",
cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
private List<HotelDetails> hotelDetails;
public City() {
}
public List<HotelDetails> getHotelDetails() {
return hotelDetails;
}
public void setHotelDetails(List<HotelDetails> hotelDetails) {
this.hotelDetails = hotelDetails;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
#Override
public String toString() {
return "City [id=" + id + ", cityName=" + cityName + "]";
}
}
2.HotelDetails Entity class
#Entity
#Table(name="hotel_details")
public class HotelDetails {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name="city_id")
private City city;
#Column(name="hotel_name")
private String hotelName;
#Column(name="available_date")
#DateTimeFormat(pattern = "dd/MM/yyyy")
private Date availableDate;
#Column(name="price")
private int price;
#Column(name="gst")
private int gst;
#Column(name="status")
private int status;
#Column(name="room_type")
private String roomType;
public HotelDetails() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public String getHotelName() {
return hotelName;
}
public void setHotelName(String hotelName) {
this.hotelName = hotelName;
}
public Date getAvailableDate() {
return availableDate;
}
public void setAvailableDate(Date availableDate) {
this.availableDate = availableDate;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getGst() {
return gst;
}
public void setGst(int gst) {
this.gst = gst;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getRoomType() {
return roomType;
}
public void setRoomType(String roomType) {
this.roomType = roomType;
}
#Override
public String toString() {
return "HotelDetails [id=" + id + ", hotelName=" + hotelName + ", availableDate=" + availableDate + ", price="
+ price + ", gst=" + gst + ", status=" + status + ", roomType=" + roomType + "]";
}
}
3.HotelDAOImpl
#Component
#Repository
public class HotelDetailsDAOImpl implements HotelDetailsDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
#Transactional
public Set<String> getHotels() {
Session currentSession = sessionFactory.getCurrentSession();
Query theQuery2 = currentSession.createQuery("Select h.hotelName from HotelDetails h");
List<String> listHotels = theQuery2.list();
Set<String> hotels = new HashSet<String>(listHotels);
return hotels;
}
#Override
#Transactional
public List<City> getAvailabilityStatus(int cityID, String hotelName, String cityName) {
Session currentSession = sessionFactory.getCurrentSession();
Query theQuery4 = currentSession.createQuery("...");
//theQuery4.setParameter("hotelName", hotelName);
//List<City> cities = theQuery4.list();
return cities;
}
}
String jpql = "select c from City c join c.hotelDetails h where h.hotelName = :hotelName";
or
String jpql = "select c from HotelDetails h join h.city c where h.hotelName = :hotelName";
and then
Query theQuery4 = currentSession.createQuery(jpql);
theQuery4.setParameter("hotelName", hotelName);
List<City> cities = theQuery4.list();
This is just an example, but once you have defined the join and the entity aliases correctly, you can refer to entity attributes in the WHERE clause any way you prefer.
For example:
jpql += " AND c.id=:id AND h.price<:price AND h.availableDate BETWEEN :start AND :end";
same for the select clause, you can use all the combinations of:
"select c.cityName, h.status, ..."
"select c, h from ..."
Check the Hibernate ORM query for many examples of how you can use JPQL/HQL.

createalias in hibernate is joining parent table two times

I have bidirectional one to many between department and employees.ie one department can have multiple employees.
I want to join department and employees using hibernate criteria so for that i am using createalias method.
Criteria criteriaDepartment = session.createCriteria(DepartmentEntity.class);
criteriaDepartment.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
criteriaDepartment.createAlias("employeeEntity", "emp",JoinType.LEFT_OUTER_JOIN);
List<DepartmentEntity> list = criteriaDepartment.list();
However, hibernate joins department table with employees and then again with the department table.
Query generated by hibernate is as follows:
Hibernate: select this_.id as id1_1_2_, this_.name as name2_1_2_, emp1_.deptId as deptId7_2_4_, emp1_.id as id1_2_4_, emp1_.id as id1_2_0_, emp1_.address as address2_2_0_, emp1_.deptId as deptId7_2_0_, emp1_.password as password3_2_0_, emp1_.phoneno as phoneno4_2_0_, emp1_.type as type5_2_0_, emp1_.userid as userid6_2_0_, department4_.id as id1_1_1_, department4_.name as name2_1_1_ from Department4 this_ left outer join Userdetails4 emp1_ on this_.id=emp1_.deptId left outer join Department4 department4_ on emp1_.deptId=department4_.id
Why Department table is joining multiple times??? Is there any way to prevent this. I have to use some restrictions as well.
However when i use fetchmode it works fine but with this method i am not able to use aliases.
Department class:
#Entity
#Table(name = "Department4")
public class DepartmentEntity {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
public int id;
public String name;
#OneToMany(mappedBy= "departmentEntity", cascade= CascadeType.ALL, orphanRemoval = true)
public Set<EmployeeEntity> employeeEntity = new HashSet<EmployeeEntity>();
public Set<EmployeeEntity> getEmployeeEntity() {
return employeeEntity;
}
public void setEmployeeEntity(Set<EmployeeEntity> employeeEntity) {
this.employeeEntity = employeeEntity;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "DepartmentEntity [id=" + id + ", name=" + name + ", employeeEntity=" + employeeEntity + "]";
}
}
Employee class
#Entity
#Table(name="Userdetails4")
public class EmployeeEntity {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
private int id;
private String userid;
private String password;
private String address;
private long phoneno;
private String type;
#ManyToOne
#JoinColumn(name = "deptId")
private DepartmentEntity departmentEntity;
#OneToMany(mappedBy = "employeeEntity", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<AddressEntity> addressEntity = new HashSet<AddressEntity>();
public Set<AddressEntity> getAddressEntity() {
return addressEntity;
}
public void setAddressEntity(Set<AddressEntity> addressEntity) {
this.addressEntity = addressEntity;
}
public DepartmentEntity getDepartmentEntity() {
return departmentEntity;
}
public void setDepartmentEntity(DepartmentEntity departmentEntity) {
this.departmentEntity = departmentEntity;
}
public EmployeeEntity()
{}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public long getPhoneno() {
return phoneno;
}
public void setPhoneno(long phoneno) {
this.phoneno = phoneno;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#Override
public String toString() {
return "EmployeeEntity [id=" + id + ", userid=" + userid + ", password=" + password + ", address=" + address
+ ", phoneno=" + phoneno + ", type=" + type + "]";
}
}
Hibernate version: 5.2.1
Thanks in advance.

could not resolve property: product_id of: Comment

Getting an error on server startup a query that finds all comments posted by a user about a specific product.
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: product_id of: haughton.dvdstore.model.Comment [select c from haughton.dvdstore.model.Comment c where c.product_id = :id]
Repo class
#Repository
public interface CommentDao extends CrudRepository<Comment,Long> {
#Query("select c from Comment c where c.product_id = :id")
List<Comment> allCommentsByProductId(#Param("id") Long id);
}
Comment class
#Entity
public class Comment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "product_id")
private Product product;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
private String text;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
My product class
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String description;
private int quantityInStock;
Date date;
private double price;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getQuantityInStock() {
return quantityInStock;
}
public void setQuantityInStock(int quantityInStock) {
this.quantityInStock = quantityInStock;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
User class
#Entity
public class User implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
#Size(min = 8, max = 20)
private String username;
#Column(length = 100)
private String password;
#Column(nullable = false)
private boolean enabled;
#OneToOne
#JoinColumn(name = "role_id")
private Role role;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(role.getName()));
return authorities;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername() {
return username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return enabled;
}
public static PasswordEncoder getPasswordEncoder() {
return PASSWORD_ENCODER;
}
}
It should have been #Query("select c from Comment c where c.product.id = :id")

Stop hibernate from firing update query on #ManyToOne entities

I have two entities ProductCartItem and Product. A product in my scenario is more of a master record that is never gonna change. Below is the mapping.
#Entity
#DiscriminatorValue(value = "PRODUCT")
public class ProductCartItem extends CartItem {
#ManyToOne(optional = false)
#JoinColumn(name = "product_id", referencedColumnName = "id")
private Product product;
#OneToMany(cascade = CascadeType.REMOVE, mappedBy = "parentProductCartItem",orphanRemoval = true)
#JsonManagedReference
Set<AccessoryCartItem> associatedAccessories = new HashSet<>();
#Column(name="property")
#Type(type = "ProductItemPropertyUserType")
private ProductItemProperty productItemProperty;
#OneToOne
#JoinColumn(name="project_id",referencedColumnName = "id")
private Project project;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Set<AccessoryCartItem> getAssociatedAccessories() {
return associatedAccessories;
}
public void setAssociatedAccessories(Set<AccessoryCartItem> associatedAccessories) {
this.associatedAccessories = associatedAccessories;
}
public void addAccessory(AccessoryCartItem accessoryCartItem) {
this.getAssociatedAccessories().add(accessoryCartItem);
}
public void removeAccessory(AccessoryCartItem accessoryCartItem) {
this.getAssociatedAccessories().remove(accessoryCartItem);
}
public ProductItemProperty getProductItemProperty() {
return productItemProperty;
}
public void setProductItemProperty(ProductItemProperty productItemProperty) {
this.productItemProperty = productItemProperty;
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
And here is the Product entity.
#Entity
public class Product extends BaseEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "title")
private String title;
#Column(name = "subtitle")
private String subtitle;
#Column(name = "description")
private String description;
#Column(name = "type_name")
private String typeName;
#Column(name = "price")
private Float price;
#Column(name = "image_list")
#Type(type = "MyImageListUserType")
private MyImageList imageList;
#Column(name = "pricing_property")
#Type(type = "PricingProperty")
private Map<String,SizePriceDTO> pricingProperty;
#JoinColumn(name = "product_type")
#ManyToOne
private ProductType productType;
private String orientation;
private Short groupId;
#Column(name = "display_order")
private Short displayOrder;
#Column(name = "base_quantity")
private int baseQuantity;
#Transient
private List<AccessoryDTO> configuredAccessoryDTOList;
public Product(){
}
public int getBaseQuantity() {
return baseQuantity;
}
public void setBaseQuantity(int baseQuantity) {
this.baseQuantity = baseQuantity;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubtitle() {
return subtitle;
}
public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
public MyImageList getImageList() {
return imageList;
}
public void setImageList(MyImageList imageList) {
this.imageList = imageList;
}
public ProductType getProductType() {
return productType;
}
public void setProductType(ProductType productType) {
this.productType = productType;
}
public String getOrientation() {
return orientation;
}
public void setOrientation(String orientation) {
this.orientation = orientation;
}
public Short getGroupId() {
return groupId;
}
public void setGroupId(Short groupId) {
this.groupId = groupId;
}
public Short getDisplayOrder() {
return displayOrder;
}
public void setDisplayOrder(Short displayOrder) {
this.displayOrder = displayOrder;
}
public List<AccessoryDTO> getConfiguredAccessoryDTOList() {
return configuredAccessoryDTOList;
}
public void setConfiguredAccessoryDTOList(List<AccessoryDTO> configuredAccessoryDTOList) {
this.configuredAccessoryDTOList = configuredAccessoryDTOList;
}
public Map<String, SizePriceDTO> getPricingProperty() {
return pricingProperty;
}
public void setPricingProperty(Map<String,SizePriceDTO> pricingProperty) {
this.pricingProperty = pricingProperty;
}
}
Now when I create a new ProductCartItem I associate an already existing Product with it. When I save the productcartitem hibernate for some reasons is firing an update query on the product table too. I have already tried setting the relationship as updatable= false but to no avail. Below is the code for the service.
private ShoppingCart addProductToCartHelper(ProductCartItemDTO productCartItemDTO) throws ShoppingException{
ShoppingCart shoppingCart;
ProductCartItem productCartItem;
Product product = productService.getProductById(productCartItemDTO.getProductDTO().getId().intValue());
if (null == product) {
throw new ShoppingException();
}
Customer currentCustomer = CanveraWebUtil.getCurrentCustomer();
GuestUser guestUser = guestUserService.loadGuestUserByUUID(CanveraWebUtil.getCurrentGuestUserIdentifier());
shoppingCart = fetchShoppingCartForCustomerOrGuestUser();
if (null == shoppingCart) {
if (null != currentCustomer) {
shoppingCart = new ShoppingCart(currentCustomer);
} else {
shoppingCart = new ShoppingCart(guestUser);
}
shoppingCart.setShoppingBagStatus(ShoppingBagStatus.DRAFT);
}
Long productCartItemDTOId = productCartItemDTO.getId();
// we will not update the associated accessories as in our case these never comes from our UI.
if (null == productCartItemDTOId) {
modifyNumberOfPages(productCartItemDTO,product);
productCartItem = new ProductCartItem();
productCartItem.setProductItemProperty(productCartItemDTO.getProductItemProperty());
productCartItem.setQuantity(productCartItemDTO.getQuantity());
productCartItem.setProduct(product);
productCartItem.setPrice(productCartItemDTO.getPrice());
productCartItem.setGiftWrap(shoppingCart.getIsGiftWrap());
//associating project
productCartItem.setProject(productCartItemDTO.getProject());
shoppingCart.addCartItem(productCartItem);
productCartItem.setShoppingCart(shoppingCart);
} else {
for (CartItem cartItem : shoppingCart.getCartItems()) {
if (null != cartItem.getId() && cartItem.getId().equals(productCartItemDTOId)) {
productCartItem = (ProductCartItem) cartItem;
productCartItem.setProductItemProperty(productCartItemDTO.getProductItemProperty());
productCartItem.setPrice(productCartItemDTO.getPrice());
productCartItem.setQuantity(productCartItemDTO.getQuantity());
}
}
}
shoppingCart = shoppingCartRepository.save(shoppingCart);
return shoppingCart;
}
Can anybody point me in the right direction ? At any point of time I do not alter any property of the product object.

need to change default join column in One to Many and Many to One Mapping i n spring data jpa

I am using spring data jpa and want to change default join column happening between the entities. For example in the following mapping,
In Account.java,
#OneToMany(mappedBy = "account")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Invoice> invoices = new HashSet<>();
In Invoice.java
#ManyToOne
private Account account;
By default the id column of Account is getting joined with account_id of Invoice as per the given one to many and many to one mapping, which is also working fine for me. But now my requirement is instead of account_id in Invoice getting joined with id of Account, I want another field account_number of Invoice to be joined with id of Account, in my one to many and many to one mappings. Is it possible? As a trail I made the following change to my Invoice
#ManyToOne
#JoinColumn(name="account_number", nullable=false)
private Account account;
But I am getting the following error:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.trace.domain.Invoice column: account_number (should be mapped with insert="false" update="false")
Account.java
/**
* Account
*/
#Entity
#Table(name = "account")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Column(name = "number", nullable = false)
private String number;
#NotNull
#Column(name = "name")
private String name;
#Column(name = "currency_code")
private String currencyCode;
#Column(name = "edi_type")
private String ediType;
#Column(name = "is_fedex_express_gsr")
private Boolean isFedexExpressGsr;
#Column(name = "is_fedex_ground_gsr")
private Boolean isFedexGroundGsr;
#Column(name = "is_ups_gsr")
private Boolean isUpsGsr;
#Column(name = "electronic_voiding")
private Boolean electronicVoiding;
#Column(name = "activate_signature_service")
private Boolean activateSignatureService;
#Column(name = "reject_invoices")
private Boolean rejectInvoices;
#Column(name = "notify_client_services")
private Boolean notifyClientServices;
#Column(name = "is_active")
private Boolean isActive;
#Column(name = "address")
private String address;
#Column(name = "city")
private String city;
#Column(name = "state")
private String state;
#Column(name = "postal_code")
private String postalCode;
#OneToMany(mappedBy = "account")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Invoice> invoices = new HashSet<>();
#ManyToOne
private Courier courier;
#ManyToOne
private Client client;
#ManyToMany
#JoinTable(
name = "account_group_members",
joinColumns = {#JoinColumn(name = "account_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "group_id", referencedColumnName = "id")})
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<AccountGroup> accountGroups = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCurrencyCode() {
return currencyCode;
}
public void setCurrencyCode(String currencyCode) {
this.currencyCode = currencyCode;
}
public String getEdiType() {
return ediType;
}
public void setEdiType(String ediType) {
this.ediType = ediType;
}
public Boolean getIsFedexExpressGsr() {
return isFedexExpressGsr;
}
public void setIsFedexExpressGsr(Boolean isFedexExpressGsr) {
this.isFedexExpressGsr = isFedexExpressGsr;
}
public Boolean getIsFedexGroundGsr() {
return isFedexGroundGsr;
}
public void setIsFedexGroundGsr(Boolean isFedexGroundGsr) {
this.isFedexGroundGsr = isFedexGroundGsr;
}
public Boolean getIsUpsGsr() {
return isUpsGsr;
}
public void setIsUpsGsr(Boolean isUpsGsr) {
this.isUpsGsr = isUpsGsr;
}
public Boolean getElectronicVoiding() {
return electronicVoiding;
}
public void setElectronicVoiding(Boolean electronicVoiding) {
this.electronicVoiding = electronicVoiding;
}
public Boolean getActivateSignatureService() {
return activateSignatureService;
}
public void setActivateSignatureService(Boolean activateSignatureService) {
this.activateSignatureService = activateSignatureService;
}
public Boolean getRejectInvoices() {
return rejectInvoices;
}
public void setRejectInvoices(Boolean rejectInvoices) {
this.rejectInvoices = rejectInvoices;
}
public Boolean getNotifyClientServices() {
return notifyClientServices;
}
public void setNotifyClientServices(Boolean notifyClientServices) {
this.notifyClientServices = notifyClientServices;
}
public Boolean getIsActive() {
return isActive;
}
public void setIsActive(Boolean isActive) {
this.isActive = isActive;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public Courier getCourier() {
return courier;
}
public void setCourier(Courier courier) {
this.courier = courier;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Set<Invoice> getInvoices() {
return invoices;
}
public void setInvoices(Set<Invoice> invoices) {
this.invoices = invoices;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Account shipper = (Account) o;
if (!Objects.equals(id, shipper.id))
return false;
return true;
}
#Override
public int hashCode() {
return Objects.hashCode(id);
}
#Override
public String toString() {
return "Account{" + "id=" + id + ", number='" + number + "'" + ", name='" + name + "'" + ", currencyCode='"
+ currencyCode + "'" + ", ediType='" + ediType + "'" + ", isFedexExpressGsr='" + isFedexExpressGsr + "'"
+ ", isFedexGroundGsr='" + isFedexGroundGsr + "'" + ", isUpsGsr='" + isUpsGsr + "'"
+ ", electronicVoiding='" + electronicVoiding + "'" + ", activateSignatureService='"
+ activateSignatureService + "'" + ", rejectInvoices='" + rejectInvoices + "'"
+ ", notifyClientServices='" + notifyClientServices + "'" + ", isActive='" + isActive + "'"
+ ", address='" + address + "'" + ", city='" + city + "'" + ", state='" + state + "'" + ", postalCode='"
+ postalCode + "'" + '}';
}
}
Invoice.java
/**
* A Invoice.
*/
#Entity
#Table(name = "invoice")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Invoice implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "account_number")
private String accountNumber;
#Column(name = "invoice_number")
private String invoiceNumber;
#Column(name = "invoice_amount")
private Double invoiceAmount;
#Column(name = "status")
private String status;
#Column(name = "edi_number")
private String ediNumber;
#Column(name = "bill_date")
private Date billDate;
#Column(name = "courier_id")
private Long courierId;
#ManyToOne
#JoinColumn(name="account_number", nullable=true)
private Account account;
#OneToMany(mappedBy = "invoice")
//#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<InvoiceDetails> invoiceDetailss = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public String getInvoiceNumber() {
return invoiceNumber;
}
public void setInvoiceNumber(String invoiceNumber) {
this.invoiceNumber = invoiceNumber;
}
public Double getInvoiceAmount() {
return invoiceAmount;
}
public void setInvoiceAmount(Double invoiceAmount) {
this.invoiceAmount = invoiceAmount;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getEdiNumber() {
return ediNumber;
}
public void setEdiNumber(String ediNumber) {
this.ediNumber = ediNumber;
}
public Date getBillDate() {
return billDate;
}
public void setBillDate(Date billDate) {
this.billDate = billDate;
}
public Long getCourierId() {
return courierId;
}
public void setCourierId(Long courierId) {
this.courierId = courierId;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Set<InvoiceDetails> getInvoiceDetailss() {
return invoiceDetailss;
}
public void setInvoiceDetailss(Set<InvoiceDetails> invoiceDetailss) {
this.invoiceDetailss = invoiceDetailss;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Invoice invoice = (Invoice) o;
if ( ! Objects.equals(id, invoice.id)) return false;
return true;
}
#Override
public int hashCode() {
return Objects.hashCode(id);
}
#Override
public String toString() {
return "Invoice{" +
"id=" + id +
", accountNumber='" + accountNumber + "'" +
", invoiceNumber='" + invoiceNumber + "'" +
", invoiceAmount='" + invoiceAmount + "'" +
", ediNumber='" + ediNumber + "'" +
", status='" + status + "'" +
", billDate='" + billDate + "'" +
", courierId='" + courierId + "'" +
'}';
}
}
As the error message says, there are two different mappings for the same column: account_number. And indeed, you have
#Column(name = "account_number")
private String accountNumber;
in your entity, which is redundant with the account field.
You just need to remove that field.

Resources