Friday, September 18, 2009

Dried Cranberries, Hong Kong Supermarket

Kaskadowość in hibernate

I will try to analyze rather unintuitive (to me) the issue of cascading save relationship in Hibernate. I will use an example already used two tables: Product and Category.

For starters: no cascading, one-sided mapping.
mappings and POJO class:

 
\u0026lt;? Xml version = "1.0"?>

\u0026lt;! DOCTYPE hibernate-mapping PUBLIC
"- / / Hibernate / Hibernate Mapping DTD 3.0 / / EN"
"http : / / hibernate.sourceforge.net/hibernate-mapping-3.0.dtd ">

\u0026lt;hibernate-mapping package="main">
\u0026lt;class name="Produkt" table="produkt">
\u0026lt;id name = "id" unsaved-value="null" column="produkt_id">
<generator class="sequence">
<param name="sequence">prod_seq</param>
</generator>
</id>
<property name="name" />
<property name="value" />
</class>
</hibernate-mapping>

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="main">
<class name="Kategoria" table="kategoria">
<id name="id" unsaved-value="null" column="kategory_id">
<generator class="sequence">
<param name="sequence">kat_seq</param>
</generator>
</id>
<property name="name" />
<property name="type" />
<property name="description" />
<set name="products" lazy="true" inverse="false" cascade="none">
<key column="kategory_id" />
<one-to-many class="Produkt" />
</set>
</class>
</hibernate-mapping>

  
package main;

public class Produkt {
Integer id;
String name;
Integer value;


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 Integer getValue () {
return value;}


public void setValue (Integer value) {
this.value = value;}



} package main;

import java.util.HashSet;
import java . util.Set;

Kategoria {public class
Integer id;
String name;
String type;
String description;
\u0026lt;Produkt> Set products = new HashSet \u0026lt;Produkt> ();

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 getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getDescription() {
return description;
}

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

\u0026lt;product> getProducts () {return
products;
} public void

setProducts (Set \u0026lt;product> products) {
this.products = products;}

}


Saving to a database category and the product is as follows:

 
package main;

org.hibernate.Session import, import
org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Main {public static void
main (String [] args) {Session session
= null;
SessionFactory SessionFactory = new Configuration (). configure (). buildSessionFactory ();
session = sessionFactory.openSession ();

Kategoria Kategoria cat = new ();
PROD1 Product = new Product ();
prod2 Product = new Product ();
kat.setName ("cat");
PROD1. setName ("PROD1");
prod2.setName ("prod2");
kat.getProducts (). add (PROD1);
kat.getProducts (). add (prod2);
session.beginTransaction ();
Session . saws (PROD1);
session.save (prod2);
session.save (cat);
session.flush ();
session.getTransaction (). commit ();
session.close ();
System. out.println ("zapisane!");
session = sessionFactory.openSession ();
session.beginTransaction ();
System.out.println ("Category:" + session.createQuery ("pious Kategoria"). Listinfo (). Size ());
System.out.println ("Produkty:" + session.createQuery ("from Product"). listinfo (). size ());
session.clear ();
session.delete (PROD1);
session.flush ();
session.getTransaction (). Commit ( );
session.close ();
System.out.println ("product usuniety");
session = sessionFactory.openSession ();
session.beginTransaction ();
System.out.println ("Category:" + session.createQuery ("pious Kategoria"). listinfo (). size ());
System.out.println ("Produkty: "+ Session.createQuery (" from Product "). List (). Size ());
session.clear ();
session.delete (cat);
session.flush ();
session.getTransaction (). commit ();
session.close ();
System.out.println ("category removed);
sessionFactory.openSession session = ();
session.beginTransaction ();
System.out.println (" Categories: "+ session.createQuery (" from Category "). list (). size ());
System.out.println (" Products: "+ session.createQuery (" from Product "). list (). size () );
System.out.println ("end");}

}


very important is to save both the product and category. If we do not, you get an error: Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: main.Produkt. The order of writing is not important.
In the code I had to clear the session (session.clear ()), to avoid the error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already-associated with the session. The result of
programiku is:
saved!
Categories: 1
Products: 2
removed
product categories: 1
Products: 1
category removed
Categories: 0
Products: 1
end


kind of ok, but why there is no product category? If you look in the database, it will actually see that in the Products table entry exists "prod2" with an empty foreign key value kategory_id. A little counterintuitive. Maybe you can do so that the dependent objects (products) are stored and disposed of together with the parent object (category)? Of course it can. You have to be just a little torment:

Mappings:
 
\u0026lt;? Xml version = "1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="main">
<class name="Kategoria" table="kategoria">
<id name="id" unsaved-value="null" column="kategory_id">
<generator class="sequence">
<param name="sequence">kat_seq</param>
</generator>
</id>
<property name="name" />
<property name="type" />
<property name="description" />
<set name="products" lazy="true" inverse="true" cascade="all">
<key column="kategory_id" />
<one-to-many class="Produkt"/>
</set>
</class>
</hibernate-mapping>

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="main">
<class name="Produkt" table="produkt">
<id name="id" unsaved-value="null" column="produkt_id">
<generator class="sequence">
<param name="sequence">prod_seq</param>
</generator>
</id>
<property name="name" />
<property name="value" />
\u0026lt;many-to-one name="kategoria" class="Kategoria" not-null="true" column="kategory_id"/>
\u0026lt;/ style>
\u0026lt;/ hibernate-mapping>


Klasy POJO:

 
main package;

import java.util.HashSet;
import java.util.Set;

Kategoria {public class
Integer id;
String name, String type
;
String description;
\u0026lt;Produkt> Set products = new HashSet \u0026lt;Produkt> ();

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 getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getDescription() {
return description;
}

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

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


public void setProducts (Set \u0026lt;Produkt> products) {
this.products = products;}


public void addProduct (Product product) {
if (product.getKategoria () == null)
product.setKategoria (this);
products.add (ProductName);}


} package main;

public class Product {
Integer id;
String name;
Integer value;
Category:

Public Category getKategoria () {
return category;}


public void setKategoria (Category) {
this.kategoria = category;
this.kategoria.getProducts (). Add (this);}


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 Integer getValue () {return value
;
} public void

setValue (Integer value) {this.value = value
;

}}


The key mappings and POJO options are "cascade", "inverse" and settery (setKatgoria, setProdukt, addProdukt) - without them javovych simple operations on the premises would not directly translate to the situation in the database.

And main:

 
package main;

org.hibernate.Session import, import
org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;


public class Main {public

static void main (String [] args) {Session

session = null;
SessionFactory SessionFactory = new Configuration (). configure (). buildSessionFactory ();
sessionFactory.openSession session = ();

session.beginTransaction () ;

Kategoria Kategoria cat = new ();
PROD1 Product = new Product ();
prod2 Product = new Product ();
prod1.setName ("PROD1");
prod2.setName ("prod2");
cat. addProduct (PROD1);
prod2.setKategoria (cat);

session.save (cat);
session.flush ();
session.getTransaction (). commit ();
session.close ();
System. out.println ("zapisane!");


session = sessionFactory.openSession ();
session.beginTransaction ();
System.out.println ("Category:" + session.createQuery ("pious Kategoria"). list (). size ());
System.out.println ("Products" + session.createQuery ("from Product"). List (). Size ());
session.clear ();
session.delete (prod1);
kat.getProducts ( ). remove (prod1);
session.flush ();
session.getTransaction (). commit ();
session.close ();
System.out.println ("product usuniety");


session = sessionFactory.openSession ();
session.beginTransaction ();
System.out.println ("Category:" + session.createQuery ("from Category"). list (). size ());
System.out.println ("Products" + session.createQuery ("from Product"). list (). size ());
session.clear ();
System.out.println ("products" + kat.getProducts (). size ());
session.delete (cat);
session.flush ();
session.getTransaction () . commit ();
session.close ();
System.out.println ("category removed);
sessionFactory.openSession session = ();
session.beginTransaction ();
System.out.println (" Categories : "+ session.createQuery (" from Category "). list (). size ());
System.out.println (" Products: "+ session.createQuery (" from Product "). list (). size ( ));
System.out.println ("end");}

}


Result the program:

saved!
Categories: 1
Products: 2
removed
product categories: 1
Products: 1
products: 1
category removed
Categories: 0
Products: 0
end

0 comments:

Post a Comment