Hi, I am having problems with many-to-many relationship mapping.
Basically, I have a Menu class that has a Map collection of SalesLineItem
objects.
Also I have a Sale that has a Map collection of SalesLineItem objects.
When the application starts up , the application first loads the Menu
containing all the SaleLineItem objects.
For example I load a Menu with 3 SalesLineItem objects.
Each SalesLineItem has a code, price, description,name and quantity
values.
Once the Menu has been loaded I can retrieve a SalesLineItem object
from the Menu by entering the SalesLineItem object's code.
// well almost like this! Hibernate requires me to retrieve the Map
// collection first, Map saleslineitems = menu.getSaleslineitems();
// But let us suppose the method below anyway!
SalesLineItem sli = menu.getSalesLineItem(String code);
Then I add the SalesLineItem in a Sale object.
HashMap map = (HashMap)sale.getSaleslineitems();
map.put(sli.getCode(),sli);
sale.setSaleslineitems(map);
This all works fine and is also persisted.
But when I increase the quantity of a SalesLineItem object, say for
example , sli.incrementQty();, and add it to the Sale object
the quantity value is also increment to the same SalesLineItem object
in the Menu.
For example I get the SalesLineItem object with code value "1" from the
Menu which corresponds to "Chicken Soup", I then add the SalesLineItem
object to the Sale and increment the SalesLineItem object's quantity
afterwards.
Once the Sale has been persisted , the "Chicken Soup" SalesLineItem
object's quantity is increased in the Menu class as well, and also in other
Sale object's that have a "Chicken Soup" SalesLineItem object
stored in their Map collection.
Some extra info:
There is a many-to-many relationship between a Menu and SalesLineItem,
because I want to be able to have different food menus, one chinese and one pizza.
And also I want a Menu to be able to have the same object that is in another menu.
For example a bottle of Coca Cola SalesLineItem.
Then I also have a many-to-many relationship between a Sale object with a SalesLineItem,
similiar principles apply here too, (just like the Menu and SalesLineItem).
below is my code, hope you can help I have been stuck with
this for 2 weeks now!
Thanks!
java files
Code:
import java.util.*;
import java.io.*;
public class SalesLineItem {
private int id;
private double price;
private double total;
private String code;
private int qty = 1;
private String name;
private String description;
public SalesLineItem(){
}
public SalesLineItem(String name,String code,double price){
this.name = name;
this.code = code;
this.price = price;
total = price * qty;
}
public void setId(int id){
this.id = id;
}
public int getId(){
return id;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setCode(String code){
this.code = code;
}
public String getCode(){
return code;
}
public void setPrice(double price){
total = price;
this.price = price;
}
public double getPrice(){
return price;
}
public void incrementQty(){
qty = qty + 1;
total = price * qty;
}
public void decrementQty(){
qty = qty - 1;
total = price * qty;
}
public void setQty(int qty){
this.qty = qty;
}
public int getQty(){
return qty;
}
public void setTotal(double total){
this.total = total;
}
public double getTotal(){
return total;
}
public String getDescription(){
return description;
}
public void setDescription(String description){
this.description = description;
}
}
class menu
Code:
import java.util.*;
import java.io.*;
public class Menu {
private String name ="";
private int id;
private int code = 0;
private Map saleslineitems;
public Menu(){
}
public void setId(int i) {
id = i;
}
public int getId() {
return id;
}
public void setCode(int code){
this.code = code;
}
public int getCode(){
return code;
}
public void setSaleslineitems(Map saleslineitems){
this.saleslineitems = saleslineitems;
}
public Map getSaleslineitems(){
return saleslineitems;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Sale class
Code:
import java.util.*;
import java.io.*;
public class Sale {
private int id;
private double total = 0;
private String type ="";
private Date date = new Date();
private Customer customer;
private Payment payment;
private Map saleslineitems = null;
private boolean onhold = false;
private boolean complete = false;
public Sale(){
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public boolean isComplete(){
return complete;
}
public void becomeComplete(){
complete = true;
}
public void setSaleslineitems(Map saleslineitems){
this.saleslineitems = saleslineitems;
}
public Map getSaleslineitems(){
return saleslineitems;
}
public boolean isOnhold(){
return onhold;
}
public void setOnhold(boolean onhold){
this.onhold = onhold;
}
public void setCustomer(Customer customer){
this.customer = customer;
}
public Customer getCustomer(){
return customer;
}
public void setPayment(Payment payment){
this.payment = payment;
}
public Payment getPayment(){
return payment;
}
public void setDate(Date date){
this.date = date;
}
public Date getDate(){
return date;
}
public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}
public double getTotal(){
double amount = 0;
Iterator it = saleslineitems.values().iterator();
while(it.hasNext()){
SalesLineItem sli = (SalesLineItem)it.next();
amount = amount + sli.getTotal();
}
setTotal(amount);
return amount;
}
public void setTotal(double total){
this.total = total;
}
public boolean hasItems(){
if(getSaleslineitems() == null){
return false;
}
else {
return true;
}
}
}
SalesDataBase
Code:
package com.ktechvision.model.sales;
import java.util.*;
import com.ktechvision.model.menu.Menu;
import com.ktechvision.model.customer.*;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import com.ktechvision.database.HibernateSession;
public class SalesDataBase {
private static SalesDataBase _instance;
private Session session;
public SalesDataBase(){
}
public static synchronized SalesDataBase getInstance() {
if (_instance != null) {
return _instance;
}
_instance = new SalesDataBase();
return _instance;
}
public void saveSale(Sale sale) throws Exception {
try {
Transaction tx = session.beginTransaction();
session.save(sale);
session.flush();
tx.commit();
}
catch (Exception e) {
e.printStackTrace();
}
}
public void open(){
if(session == null){
try{
session = HibernateSession.currentSession();
}catch(Exception e){
e.printStackTrace();
}
}
}
public void close(){
try{
session.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
SQL
Code:
create database products;
use products;
create table menu (
id int not null auto_increment primary key,
code integer,
name text
);
create table saleslineitem (
id int not null auto_increment primary key,
price double,
total double,
code text,
qty int,
name text,
description text
);
create table menu_saleslineitem (
parent_id int,
saleslineitem_name text,
saleslineitem_id int
);
create table sale (
id int not null auto_increment primary key,
customer_id int,
type text,
date date,
total double
);
create table sale_saleslineitem(
parent_id int,
saleslineitem_name text,
saleslineitem_id int
);
Hibernate mapping xml file
This is of course not the whole file,only classes discussed
are shown in this mapping.
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="com.ktechvision.model.menu.Menu"
table="menu">
<id name="id" unsaved-value="0">
<generator class="native"/>
</id>
<map name="saleslineitems"
table="menu_saleslineitem" cascade="all">
<key column="parent_id"/>
<index column="saleslineitem_name" type="string"/>
<many-to-many column="saleslineitem_id" class="com.ktechvision.model.menu.SalesLineItem"/>
</map>
<property name="name" type="string"/>
<property name="code" type="int"/>
</class>
<class name="com.ktechvision.model.menu.SalesLineItem"
table="saleslineitem">
<id name="id" unsaved-value="0">
<generator class="native"/>
</id>
<property name="name" type="string"/>
<property name="description" type="string"/>
<property name="price" type="double"/>
<property name="code" type="string"/>
<property name="qty" type="int"/>
<property name="total" type="double"/>
</class>
<class name="com.ktechvision.model.sales.Sale"
table="sale">
<id name="id" unsaved-value="0">
<generator class="native"/>
</id>
<map name="saleslineitems"
table="sale_saleslineitem" cascade="all">
<key column="parent_id"/>
<index column="saleslineitem_name" type="string"/>
<many-to-many column="saleslineitem_id" class="com.ktechvision.model.menu.SalesLineItem"/>
</map>
<property name="date" type="date"/>
<property name="type" type="string"/>
<property name="total" type="double"/>
</class>
</hibernate-mapping>
other hibernate files
Code:
hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class com.mysql.jdbc.Driver
hibernate.connection.url jdbc:mysql://localhost/products
hibernate.connection.username root
hibernate.connection.password secret
hibernate.show_sql true
hibernate.cglib.use_reflection_optimizer false
hibernate.connection.pool_size 5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/products</property>
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<mapping resource="Version.hbm.xml"/>
</session-factory>
</hibernate-configuration>
log4j.rootCategory=INFO, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-5p - %m%n