I am new to Hibernate. I have two classes "quotation" and "quotation_item"
their database structure is like this
create table quotation
(
quotation_id int primary key auto_increment,
code varchar(20),
client_name varchar(20)
);
create table quotation_item
(
id int primary key auto_increment,
quotation_id int,
item_name varchar(20),
rate int,
qty int,
FOREIGN KEY (quotation_id) REFERENCES quotation(quotation_id)
);
Quotation.hbm.xml is like this,
<hibernate-mapping>
<class name="com.paramatrix.pojo.Quotation" table="quotation">
<id name="quotationId" type="int" column="quotation_id">
<generator class="native" />
</id>
<property name="code" column="code" type="string" />
<property name="clientName" column="client_name" type="string" />
<set name="quotationItem" table="quotation_item" fetch="select" cascade="all">
<key>
<column name="quotation_id" not-null="true" />
</key>
<one-to-many class="com.paramatrix.pojo.QuotationItem" />
</set>
</class>
</hibernate-mapping>
QuotationItem.hbm.xml is like this,
<hibernate-mapping>
<class name="com.paramatrix.pojo.QuotationItem" table="quotation_item">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<many-to-one name="quotation" class="com.paramatrix.pojo.Quotation" cascade="save-update">
<column name="quotation_id" not-null="true" />
</many-to-one>
<property name="itemName" column="item_name" type="string" />
<property name="rate" column="rate" type="int" />
<property name="qty" column="qty" type="int" />
</class>
</hibernate-mapping>
POJO's are
1>Quotation.java
public class Quotation {
int quotationId;
String code;
String clientName;
Set<QuotationItem> quotationItem=new HashSet<QuotationItem>();
//getter& setter
}
2>QuotationItem.java
public class QuotationItem{
int id;
Quotation quotation;
String itemName;
int rate;
int qty;
//getter and setter
}
main method is
Set<QuotationItem> set=new HashSet<QuotationItem>();
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session=factory.openSession();
session.beginTransaction();
Quotation quotation = new Quotation();
quotation.setCode(txtCode.getValue());
quotation.setClientName(txtClientName.getValue());
QuotationItem quotationItem = new QuotationItem();
quotationItem.setItemName(txtItemName.getValue());
quotationItem.setQty(Integer.parseInt( txtQty.getValue()));
quotationItem.setRate(Integer.parseInt(txtRate.getValue()));
set.add(quotationItem);
quotation.setQuotationItem(set);
session.saveOrUpdate((quotation));
session.getTransaction().commit();
System.out.println("Done");
Try quotationItem.setQuotation(quotation)
Related
I have an object User, which has a List of UserDictionary. Each UserDictionary has a List of UserWords with cascade delete.
User.java
public class User implements Serializable
{
private Long id;
private String login;
private String password;
private String email;
private Boolean isVerified;
private List<UserDictionary> dictionaries = new ArrayList<>();
private UserTrainingSettings settings;
//getters and setters there
}
And mapping User.hbm.xml
<hibernate-mapping>
<class name="User" dynamic-insert="true" dynamic-update="true" table="USER" entity-name="user">
<id name="id" type="java.lang.Long" column="user_id">
<generator class="native"/>
</id>
<property name="login" type="java.lang.String" length="40" not-null="true" unique="true"/>
<property name="password" type="java.lang.String" length="32" not-null="true"/>
<property name="email" type="java.lang.String" length="100" not-null="true"/>
<property name="isVerified" type="java.lang.Boolean" column="verified" not-null="true"/>
<list name="dictionaries" fetch="join">
<key column="user_id" not-null="true" on-delete="cascade"/>
<one-to-many class="com.github.wordsmemoriser.Model.UserDictionary"/>
</list>
<one-to-one name="settings" class="com.github.wordsmemoriser.Model.UserTrainingSettings"
cascade="javax.persistence.CascadeType.REMOVE"/>
</class>
</hibernate-mapping>
UserDictionary.java
public class UserDictionary
{
private Long id;
private User user;
private String name;
private List<UserWords> words = new ArrayList<>();
//getters and setters there
}
And mapping UserDictionary.hbm.xml
<hibernate-mapping>
<class name="UserDictionary" dynamic-insert="true" dynamic-update="true" table="DICTIONARY">
<id name="id" type="java.lang.Long" column="dict_id">
<generator class="native"/>
</id>
<many-to-one name="user" class="com.github.wordsmemoriser.Model.User" fetch="join">
<column name="user_id" not-null="true"/>
</many-to-one>
<property name="name" type="java.lang.String" length="100"/>
<list name="words">
<key column="dict_id" not-null="true" on-delete="cascade"/>
<one-to-many class="com.github.wordsmemoriser.Model.UserWords"/>
</list>
</class>
</hibernate-mapping>
What is a proper way to delete all UserDictionaries from User? Should I iterate this list, delete every UserDictionary from database, then clear this list and update User like this
session.beginTransaction();
for(UserDictionary dict : user.getDictionaries())
{
session.delete(dict);
}
user.getDictionaries().clear();
session.update(user);
session.getTransaction().commit();
or should I just clear User's list and then update it like this
user.getDictionaries().clear();
session.beginTransaction();
session.update(user);
session.getTransaction().commit();
I have two classes :
Etudiant and Pays
In the database the table Etudiant has a foreign key for the table Pays.
In my code I have something like this :
List<Etudiant> listEtudiants = (List<Etudiant>) etudiantService.getAll();
for(Etudiant etudiant : listEtudiants) {
if(((JTextField)arg0.getSource()).getText().equals(etudiant.getNom())){
System.out.println(etudiant.getPays().getNom());
}
}
but when I run this code it fails with the exception:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
In the line :
System.out.println(etudiant.getPays().getNom());
Mapping for Etudiant:
<hibernate-mapping>
<class name="tp.ihm.domain.Etudiant" table="etudiant" schema="public" optimistic-lock="version">
<id name="numInsc" type="java.lang.Long">
<column name="num_insc" />
<generator class="assigned" />
</id>
<many-to-one name="pays" class="tp.ihm.domain.Pays" fetch="select">
<column name="pays" not-null="true" />
</many-to-one>
<property name="nom" type="string">
<column name="nom" length="50" not-null="true" />
</property>
<property name="prenom" type="string">
<column name="prenom" length="50" not-null="true" />
</property>
</class>
</hibernate-mapping>
Mapping for Pays:
<hibernate-mapping>
<class name="tp.ihm.domain.Pays" table="pays" schema="public" optimistic-lock="version">
<id name="id" type="java.lang.Long">
<column name="id" />
<generator class="assigned" />
</id>
<property name="nom" type="string">
<column name="nom" length="45" not-null="true" />
</property>
<set name="etudiants" table="etudiant" inverse="true" lazy="true" fetch="select">
<key>
<column name="pays" not-null="true" />
</key>
<one-to-many class="tp.ihm.domain.Etudiant" />
</set>
</class>
</hibernate-mapping>
I tried to remove the fetch attribute in the mapping for Pays, and then to change it's value to eager but nothing works.
Could someone please help me with this ?
Edit :
This is the code for the getAll method :
public List getAll() throws EntityNotFoundException {
// Get the current session
Session s = getSession();
List list = null;
// If the BLL layer started a transaction
// In this case it is the BLL layer that manages the session and transaction
if (anActiveTransactionExist(s)) {
list = s.createCriteria(Etudiant).list();
} else {
LOGGER.debug("DAO initialize its own transaction");
Transaction tx = null;
try {
// Starts a transaction locally
tx = s.beginTransaction();
list = s.createCriteria(boClass).list();
tx.commit();
} catch (RuntimeException ex) {
// Cancel the transaction if there is a problem
handleDaoOpError(tx, ex);
} finally {
closeSession(s);
}
}
if (list == null || list.size() == 0)
throw new EntityNotFoundException();
return list;
}
You need to change the mapping of Etudiant from fetch=select to fetch=join
fetch-“join” = Disable the lazy loading, always load all the collections and entities.
fetch-“select” (default) = Lazy load all the collections and entities.
<many-to-one name="pays" class="tp.ihm.domain.Pays" fetch="join">
<column name="pays" not-null="true" />
</many-to-one>
I have two tables in a one-to-many relationship mapped by Hibernate:
<hibernate-mapping>
<class name="Class1" table="TABLE_1" dynamic-update="true">
<meta attribute="implement-equals">true</meta>
<cache usage="read-write"/>
<id name="id" column="KEY_1" length="5" >
....
</id>
<property name="property1a" column="COLUMN_1A" type="string" length="10" />
<property name="property1b" column="COLUMN_1B" type="string" length="10" />
<set name="properties2Set" table="TABLE_2" lazy="true" fetch="subselect" cascade="all">
<key column="FOREIGN_KEY_1"/>
<composite-element class="Class2">
<property name="property2a" type="string" column="COLUMN_2A"/>
<property name="property2b" type="string" column="COLUMN_2B"/>
<property name="property2c" type="string" column="COLUMN_2C"/>
</composite-element>
</set>
</class>
</hibernate-mapping>
Class1 looks like:
public class Class1
{
//... Here the definitions of property1a, property1b
private Set<Class2> properties2Set = new HashSet<Class2>();
public Set<Class2> getProperties2Set()
{
return properties2Set;
}
public void setProperties2Set(Set<Class2> properties2Set)
{
this.properties2Set = properties2Set;
}
// ... Definitions of equals() and hashCode()
}
Class2 contains properties property2a, property2b, property2c. There is a constraint
CONSTRAINT PK_OLD PRIMARY KEY (FOREIGN_KEY_1, COLUMN_2A, COLUMN_2B, COLUMN_2C)
I want to add to the table the column
COLUMN_ID_NUMBER NUMBER(5) DEFAULT 0 NOT NULL
change the constraint into
CONSTRAINT PK_NEW PRIMARY KEY (FOREIGN_KEY_1, COLUMN_ID_NUMBER)
and generate values of COLUMN_ID_NUMBER in order not to violate the constraint.
Where to add the property that would be mapped into COLUMN_ID_NUMBER and how to generate its values? Is it possible to leave the structure of Class2 unchanged?
I'm working on online exam project by using Struts Spring and Hibernate integration with mysql & Eclipse kepler.
While submitting the values in registration.jsp page, i'm trying to store that values in two different tables (user_details,address) within the same database. I can able to store them in DB, but i can't able to fetch the user_id which is a foreign key for address table. user_id is the primary key in user_details table.Except user_id in address table, all the other fields are filled with the correct values. I'm trying to use that in address table. But i can't do that. I have attached the code that i'm using right now,
user.hbm.xml
<hibernate-mapping>
<class name="UserDetails" table="user_details">
<id name="user_id" type="int" column="user_id" >
<generator class="identity">
</generator>
</id>
<property name="first_name" type="string">
<column name="first_name"/>
</property>
<property name="last_name" type="string">
<column name="last_name"/>
</property>
<property name="email" type="string">
<column name="email"/>
</property>
<property name="password" type="string">
<column name="password"/>
</property>
<property name="gender" type="string">
<column name="gender"/>
</property>
<property name="dob" type="int">
<column name="dob"/>
</property>
<property name="phone" type="int">
<column name="phone"/>
</property>
<property name="experience" type="float">
<column name="experience"/>
</property>
<set name="addr" table="address"
inverse="true" lazy="true" fetch="select" cascade = "save-update">
<key>
<column name="user_id" not-null="false" />
</key>
<one-to-many class="UserAddress" />
</set>
</class>
</hibernate-mapping>
useraddress.hbm.xml
<hibernate-mapping>
<class name="UserAddress" table="address">
<id name="address_id" type="int" column="address_id">
<generator class="identity"/>
</id>
<property name="addr_line1" type="string">
<column name="addr_line_1"/>
</property>
<property name="addr_line2" type="string">
<column name="addr_line_2"/>
</property>
<property name="addr_line3" type="string">
<column name="addr_line_3"/>
</property>
<property name="city" type="string">
<column name="city"/>
</property>
<property name="zipcode" type="int">
<column name="zipcode"/>
</property>
<property name="state" type="string">
<column name="state"/>
</property>
<property name="country" type="string">
<column name="country"/>
</property>
<many-to-one name="user_detail" class="UserDetails" fetch="select">
<column name="user_id" not-null="false"></column>
</many-to-one>
</class>
</hibernate-mapping>
UserDetails.java
public class UserDetails {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
//#OneToMany (mappedBy="user_details", cascade = CascadeType.ALL)
#OneToMany (cascade = { CascadeType.PERSIST, CascadeType.MERGE}, mappedBy="user_detail")
public int user_id; //primary key
private String first_name;
private String last_name;
private String email;
private String password;
private String gender;
private int dob;
private int phone;
private float experience;
private Set<UserAddress> addr;//set name
//getters and setters created
UserAddress.java
public class UserAddress {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int address_id; //primary key
#ManyToOne(fetch=FetchType.EAGER, targetEntity=UserDetails.class)
#JoinColumn(name="user_id")
private UserDetails user_detail;
private String addr_line1;
private String addr_line2;
private String addr_line3;
private String city;
private int zipcode;
private String state;
private String country;
//getters and setters created
I think i'm missing something in hibernate mapping part, because i can able to store other address table values except user_id. If anyone is interested to work with the complete code
Hi
I’m trying to map some classes in hibernate there and have general problem how such mapping can be done.
There is User class and Facebook user class which has the following structure
User Class :
public class User{
public User(){}
Long Id;
String FirstName;
String LastName;
....
FbUser fbuser;
//// all requred
getters and setters...
}
Facebook class FbUser can have list of Friends which are objects of the same class FbUser.
public class FbUser{
public FbUser(){}
Long fbId;
String FirstName;
String LastName;
List<FbUser> friends;
//// all requred
getters and setters...
}
Till now I made many to one relation between User And FbUser.
<hibernate-mapping>
<class
name="User"
table="User"
>
<id
name="Id"
column="ID"
type="java.lang.Long"
unsaved-value="null"
>
<generator class="increment"/>
</id>
<property
name="FirstName"
update="true"
insert="true"
not-null="false"
unique="false"
type="java.lang.String"
>
<column name="FirstName" />
</property>
<property
name="LastName"
update="true"
insert="true"
not-null="false"
unique="false"
type="java.lang.String"
>
<column name="LastName" />
</property>
<many-to-one
name="fbUser"
class="FbUser"
cascade="all"
column="fbId"
unique="true"
/>
</class>
</hibernate-mapping>
And now the FbUser Mapping:
<hibernate-mapping>
<class
name="FbUser"
table="FbUser"
>
<id
name="fbId"
column="fbId"
type="java.lang.Long"
unsaved-value="null"
>
<generator class="increment"/>
</id>
<property
name="FirstName"
update="true"
insert="true"
not-null="false"
unique="false"
type="java.lang.String"
>
<column name="FirstName" />
</property>
<property
name="LastName"
type="java.lang.String"
update="true"
insert="true"
column="LastName"
not-null="true"
unique="false"
/>
</class>
</hibernate-mapping>
Chow can I map FbUser List inside the FbUser Map file? I got lost :(
You can create an additional class named, for instance, MyFriends
public class FbUser {
List<MyFriends> friends = new ArrayList<MyFriends>();
}
Just relevant part
If you have a index-column
<hibernate-mapping>
<class name="FbUser">
<list name="myFriends">
<key column="ME_ID" insert="false" update="false"/>
<list-index column="WHICH COLUMN SHOULD BE USED AS INDEX"/>
<one-to-many class="MyFriends"/>
</list>
</class>
</hibernate-mapping>
If you do not have a index-column
re-write your list as
public class FbUser {
Collection<MyFriends> friends = new ArrayList<MyFriends>();
}
And
<hibernate-mapping>
<class name="FbUser">
<bag name="columns">
<key column="ME_ID" insert="false" update="false"/>
<one-to-many class="MyFriends"/>
</bag>
</class>
</hibernate-mapping>
And your MyFriends mapping. Notice you need a composite primary key (implemented as a static inner class)
<class name="MyFriends">
<composite-id name="myFriendsId" class="MyFriends$MyFriendsId">
<key-property name="meId"/>
<key-property name="myFriendId"/>
</composite-id>
<many-to-one name="me" class="FbUser" insert="false" update="false"/>
<many-to-one name="myFriend" class="FbUser" insert="false" update="false"/>
</class>
Your MyFriends is shown as follows
public class MyFriends {
private MyFriendsId myFrinedId;
private FbUser me;
private FbUser myFriend;
public static class MyFriendsId implements Serializable {
private Integer meId;
private Integer myFriendId;
// getter's and setter's
public MyFriendsId() {}
public MyFriendsId(Integer meId, Integer myFriendId) {
this.meId = meId;
this.myFriendId = myFriendId;
}
// getter's and setter's
public boolean equals(Object o) {
if(!(o instanceof MyFriendsId))
return false;
MyFriendsId other = (MyFriendsId) o;
return new EqualsBuilder()
.append(getMeId(), other.getMeId())
.append(getMyFriendId(), other.getMyFriendId())
.isEquals();
}
public int hashcode() {
return new HashCodeBuilder()
.append(getMeId())
.append(getMyFriendId())
.hashCode();
}
}
}
Well, first: User has a one-to-one relation with FbUser, correct?
second: Map FbUser to FbUser as a many to many relation using a list or a set. I have an Set example here:
<set
name="friends"
table="FbUser" <!-You may use other table here if you want->
access="field">
<key
column="fbId"/>
<many-to-many
class="bla.bla.bla.FbUser"
column="friend_id" />
</set>