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 extends UserDetails {
#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, i'm ready to give. Thanks.
What is the error in stacktrace?
Also you should use annotations for mapping columns & attributes.
Have you put mapping resource in hibernate configuration file?
Related
I have two tables: patient_data and patient_diagnosis
Patient_data contains personal data of patient like: pid (pkey), gender, birth_date
patient_diagnosis contains the diagnosis data of the registered patients. It has fields like: record_id (pkey), pid (fkey to patient_data(pid)), diagnosis_date and other related fields.
Now, I want to join these two tables on pid and have all these fields in a single type of object.
Here is the mapping file:
<hibernate-mapping>
<class catalog="emr" name="in.Models.Emr" table="patient_diagnosis">
<id name="recordid" type="long">
<column name="record_id"/>
</id>
<property name="diagnosisDate" type="timestamp">
<column length="19" name="diagnosis_date" not-null="true"/>
</property>
<property name="snomedTermPrimary" type="long">
<column name="snomed_term_primary" not-null="true" />
</property>
<property name="snomedTermSecondary" type="string">
<column name="snomed_term_secondary" />
</property>
<property name="episodeNo" type="long">
<column name="episode_no" not-null="true" />
</property>
<property name="pid" type="long">
<column name="pid" not-null="true" />
</property>
<join table="patient_data">
<key column="pid"/>
<property name="gender" type="string">
<column name="gender" not-null="true"/>
</property>
<property name="birthDate" type="timestamp">
<column length="19" name="birth_date" not-null="true"/>
</property>
</join>
</class>
</hibernate-mapping>
But, the join applies on patient_diagnosis.record_id = patient_data.pid instead of patient_diagnosis.pid = patient_data.pid i.e. HQL applies on primary key of first table with mentioned column from second table.
Please provide the solution so that join can be applied on mentioned column from first with mentioned column from second table. Or is there another way out?
Please note that in case I didn't create classes for patient_data or patient_diagnosis. But, just Emr class having combination of fields of these tables is created.
Try giving foreign key
<id name="pid" type="java.lang.Long">
<column name="pid" />
<generator class="foreign">
<param name="property">patient_data</param>
</generator>
</id>
I am not sure but maybe this should work.
And
<one-to-one name="patient_data" class="in.Models.Emr"
cascade="save-update"></one-to-one>
Similarly in Join class
<one-to-one name="patient_diagnosis" class="in.Models.Emr"
cascade="save-update"></one-to-one>
I hope this helps you.
I have 2 classes Device and Position that have a relation one-to-many/many-to-one (One device has several positions, a position is associated to one and only one device).
I have clearly specified in the hibernate mapping file that I want my table to join on device.DeviceID = position.FK_DeviceID, yet when i execute the following HQL query:
String queryString = "select position"
+ " from Position position join position.device device"
+ " where device.MACAddress = '" + macAddress + "'";
I keep getting the error : " ERROR: Unknown column 'position0_.deviceID' in 'field list' ", indicating me that he tries to join on "deviceID" and not "FK_deviceID".
Here are the classes and the mapping files:
Position:
private Integer positionID;
private Coordinate coordinate;
private Date timestamp;
private Device device;
Device:
private Integer deviceID;
private String MACAddress;
private String name;
private Set<Position> positions;
Device mapping:
<hibernate-mapping>
<class name="fr.utbm.LO53_IPS.models.Device" table="device" catalog="bdd_LO53">
<id name="deviceID" type="java.lang.Integer">
<column name="deviceID" />
<generator class="identity" />
</id>
<property name="MACAddress" type="string">
<column name="MACAddress" length="45" not-null="true"/>
</property>
<property name="Name" type="string">
<column name="Name" length="45" not-null="false" />
</property>
<set name="positions" cascade="all">
<key column="FK_DeviceID"/>
<one-to-many class="fr.utbm.LO53_IPS.models.Position" />
</set>
</class>
Position mapping:
<hibernate-mapping>
<class name="fr.utbm.LO53_IPS.models.Position" table="position" catalog="bdd_LO53">
<id name="PositionID" type="java.lang.Integer">
<column name="deviceID" />
<generator class="identity" />
</id>
<property name="Timestamp" type="java.sql.Date">
<column name="Timestamp" not-null="true"/>
</property>
<many-to-one name="device" column="FK_DeviceID"
class="fr.utbm.LO53_IPS.models.Device" not-null="true"/>
<component name="Coordinate" class="fr.utbm.LO53_IPS.models.Coordinate">
<property name="x" type="java.lang.Integer">
<column name="x" not-null="true" />
</property>
<property name="y" type="java.lang.Integer">
<column name="y" not-null="true" />
</property>
</component>
</class>
Sorry for the long post, I really can't figure out what part is wrong.
In the mapping for class Position, when you declare the id you are specifying a column called deviceID, which is a bit strange, because you should have a column PositionID, since you are in the table Position.
On the other hand, you can easily join like this: from Position p where p.device.MACAddres='....' without using join explicitly.
Here I am trying to create hibernet mapping between three tables.
atom stores user unique name and id, post_messages stores messages
likes is a table which store likes of messages by users(atom).
One user(atom) can like multiple messages.
and multiple user(atom) can like a single message.
one user can like a particular message once
Data in likes table will store whenever user(atom) click on like button of message(on jsp page)
My table structure are as given below
atom
CREATE TABLE `atom` (
`id` int(100) NOT NULL AUTO_INCREMENT,
`name` varchar(200),
`type` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
unique KEY (name)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
likes
CREATE TABLE likes (
messageid bigint(200) NOT NULL,
aid int(100) NOT NULL,
adddate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (messageid,aid),
CONSTRAINT messageid FOREIGN KEY (messageid) REFERENCES post_messages(messageid) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `aid` FOREIGN KEY (aid) REFERENCES atom (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
post_messages
CREATE TABLE `post_messages` (
`messageid` bigint(200) NOT NULL AUTO_INCREMENT,
`message` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`messageid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I want to create classes and hbm.xml file for above table
To solve above I have created classes according to tables as below
Atom
public class Atom implements java.io.Serializable {
private Integer id;
private String name;
private String type;
private Set postMessages=new Hashset(0);
//getter setter and constructor of above
}
PostMessages
public class PostMessages implements java.io.Serializable {
private Long messageid;
private String message;
private Set likes = new HashSet(0);
//getter setter and constructor of above
}
Likes
public class Likes implements java.io.Serializable {
private Long messageid;
private Integer aid;
private Atom atom;
private PostMessages postMessages;
private Date adddate;
//getter setter and constructor of above
}
Hibernate mapping files
Atom.hbm.xml
<hibernate-mapping>
<class name="hibernetMappings.Atom" table="atom" catalog="xrcwrn_sms">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="name" length="200" unique="true" />
</property>
<property name="type" type="string">
<column name="type" length="100" not-null="true" />
</property>
<set name="likes" table="likes" inverse="true" lazy="true" fetch="select">
<key>
<column name="aid" not-null="true" />
</key>
<one-to-many class="hibernetMappings.Likes" />
</set>
</hibernate-mapping>
PostMessages.hbm.xml
<hibernate-mapping>
<class name="hibernetMappings.PostMessages" table="post_messages" catalog="xrcwrn_sms">
<id name="messageid" type="java.lang.Long">
<column name="messageid" />
<generator class="identity" />
</id>
<property name="message" type="string">
<column name="message" length="1000" />
</property>
<property name="visibility" type="string">
<column name="visibility" length="100" />
</property>
<property name="totalLikes" type="java.lang.Long">
<column name="total_likes" />
</property>
<set name="likes" table="likes" inverse="true" lazy="true" fetch="select">
<key>
<column name="messageid" not-null="true" />
</key>
<one-to-many class="hibernetMappings.Likes" />
</set>
</hibernate-mapping>
Likes.hbm.xml
<hibernate-mapping>
<class name="hibernetMappings.Likes" table="likes" catalog="xrcwrn_sms">
<composite-id name="id" class="hibernetMappings.Likes">
<key-property name="messageid" type="long">
<column name="messageid" />
</key-property>
<key-property name="aid" type="int">
<column name="aid" />
</key-property>
</composite-id>
<many-to-one name="atom" class="hibernetMappings.Atom" update="false" insert="false" fetch="select">
<column name="aid" not-null="true" />
</many-to-one>
<many-to-one name="postMessages" class="hibernetMappings.PostMessages" update="false" insert="false" fetch="select">
<column name="messageid" not-null="true" />
</many-to-one>
<property name="adddate" type="timestamp">
<column name="adddate" length="19" not-null="true" />
</property>
</hibernate-mapping>
What changes should I do in above. To make it correct.
I am looking into Hibernate's parent/child relationships.
I have 3 entities Employee Customers and Orders.
Their relationship is
Employee 1 <-> N Orders
Customer 1 <-> N Orders
I want to be able to save/update/delete Customer objects and Employees and Orders but I want to use some interface so that the calling code does not deal with any Hibernate or JPA stuff.
E.g. I tried something like the following:
class Utils{
public static void saveObject(Object o){
logger.debug(o.toString());
Session session = getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(o);
tx.commit();
session.close();
}
}
and in the calling code I do:
Employee employee = new Employee();
//set data on employee
Customer customer = new Customer();
//set data on customer
Order order = new Order();
//set data on order
employee.addOrder(order);//this adds order to its list, order gets a reference of employee as parent
customer.addOrder(order);//this adds order to its list, order gets a reference of customer as parent
Utils.saveObject(customer);
Utils.saveObject(employee);
Now I noticed that with this code, 2 records of employee are created instead of 1.
If I only do:
Utils.saveObject(customer);
Only 1 (correctly) record is created.
Why does this happen?
Does this happens because the same Order object is saved by both Customer and Employee? And the cascade="all" makes this side-effect?
Now if I do not use the DBUtils method and do directly:
Session session = DBUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(employee);
session.save(customer);
tx.commit();
session.close();
Again, it works as expected. I.e. only 1 employee record is created.
What am I doing something wrong here?
UPDATE:
Hibernate mappings:
<hibernate-mapping>
<class name="database.entities.Associate" table="EMPLOYEE">
<id name="assosiateId" type="java.lang.Long">
<column name="EMPLOYEEID" />
<generator class="identity" />
</id>
<property name="firstName" type="java.lang.String" not-null="true">
<column name="FIRSTNAME" />
</property>
<property name="lastName" type="java.lang.String" not-null="true">
<column name="LASTNAME" />
</property>
<property name="userName" type="java.lang.String" not-null="true">
<column name="USERNAME" />
</property>
<property name="password" type="java.lang.String" not-null="true">
<column name="PASSWORD" />
</property>
<set name="orders" table="ORDERS" inverse="true" cascade="all" lazy="true">
<key>
<column name="EMPLOYEEID" />
</key>
<one-to-many class="database.entities.Order" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="database.entities.Customer" table="CUSTOMER">
<id name="customerId" type="java.lang.Long">
<column name="CUSTOMERID" />
<generator class="identity" />
</id>
<property name="customerName" type="java.lang.String">
<column name="CUSTOMERNAME" />
</property>
<set name="orders" table="ORDERS" inverse="true" cascade="all" lazy="true">
<key>
<column name="CUSTOMERID" />
</key>
<one-to-many class="database.entities.Order" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="database.entities.Order" table="ORDERS">
<id name="orderId" type="java.lang.Long">
<column name="ORDERID" />
<generator class="identity" />
</id>
<property name="orderDate" type="java.util.Date">
<column name="ORDERDATE" />
</property>
<property name="quantity" type="java.lang.Integer">
<column name="QUANTITY" />
</property>
<property name="quantityMargin" type="java.lang.Long">
<column name="QUANTITYMARGIN" />
</property>
<property name="port" type="java.lang.String">
<column name="PORT" />
</property>
<property name="orderState" type="java.lang.String">
<column name="ORDERSTATE" />
</property>
<many-to-one name="customer" class="database.entities.Customer" cascade="all" fetch="join">
<column name="CUSTOMERID" />
</many-to-one>
<many-to-one name="associate" column="EMPLOYEEID" class="database.entities.Employee" cascade="all" fetch="join">
</many-to-one>
</class>
</hibernate-mapping>
UDATE 2:
class Employee{
//Various members
Set<Order> orders = new HashSet<Order>();
public void addOrder(Order order){
order.setEmployee(this);
orders.add(order);
}
}
Also:
class Customer{
//Various members
Set<Order> orders = new HashSet<Order>();
public void addOrder(Order order){
order.setCustomer(this);
orders.add(order);
}
}
It seems to me that in the DBUtils code, you are wrapping both saves in an outer transaction, whereas in the Utils code, you have them in two completely separate transactions without an outer one.
Depending on your cascading, Hibernate has to figure out which objects need to be saved. When you run the Utils code, with two separate transactions, it will save the Order first. Since you're cascading all, this means it will save the Order first, then the Customer. However, you've created the SAME Order for both the Customer and Employee. Therefore, the Employee also gets saved in the first transaction (due to cascading). The second transaction, since it is separate, will not be aware of this and save another Employee.
On the other hand, if you wrap them in an outer transaction, Hibernate can figure out the identities of all the objects and save them properly.
try saving only Order instead of saving Employee and Customer separately. With your existing cascade=all setting both parent object will get saved without creating any duplicates.
Problem #1:
I have three tables; User, UserRole, and UserRoleRelationships (join table). The UserRole table contain all the user roles which I want to associate with the user. When I insert a new user I want to add a new user and add a new association in the join table. Now, when I'm running the query for inserting a new user:
IWUser iwUser = new IWUser();
iwUser.setUsername("username");
iwUser.setFullName("fullName");
iwUser.setEmail("email");
iwUser.setPassword("password");
iwUser.setPrivatephone("55555");
iwUser.setWorkphone("777");
Set<IWUserRole> roleList = new HashSet<IWUserRole>();
IWUserRole iwUserRole = new IWUserRole();
iwUserRole.setRole("ROLE_USER");
roleList.add(iwUserRole);
iwUser.setUserRole(roleList);
iwUserManagementService.saveOrUpdate(iwUser);
hibernate is running the following queries:
Hibernate: insert into dbo.Users (Username, Password, Email, Workphone, Privatephone, FullName) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into dbo.UserRoles (Role) values (?)
Hibernate: insert into UserRoleRelationships (UserId, RoleId) values (?, ?)
My hibernate mapping looks like:
IWUser.hbm.xml:
<hibernate-mapping>
<class name="domain.IWUser" schema="dbo" table="Users">
<id name="userId" type="int">
<column name="UserId"/>
<generator class="native"/>
</id>
<property name="username" type="string">
<column name="Username" not-null="true"/>
</property>
<property name="password" type="string">
<column name="Password" not-null="true"/>
</property>
<property name="email" type="string">
<column name="Email" not-null="false"/>
</property>
<property name="workphone" type="string">
<column name="Workphone" not-null="false"/>
</property>
<property name="privatephone" type="string">
<column name="Privatephone" not-null="false"/>
</property>
<property name="fullName" type="string">
<column name="FullName" not-null="false"/>
</property>
<set cascade="all" inverse="false" name="userRole" table="UserRoleRelationships" lazy="true" >
<key>
<column name="UserId"/>
</key>
<many-to-many class="domain.IWUserRole" column="RoleId"/>
</set>
</class>
</hibernate-mapping>
IWUserRole.hbm.xml:
<hibernate-mapping>
<class name="domain.IWUserRole" schema="dbo" table="UserRoles">
<id name="roleId" type="int">
<column name="RoleId"/>
<generator class="native"/>
</id>
<property name="role" type="string">
<column name="Role" not-null="true"/>
</property>
<set cascade="all" inverse="false" name="user" table="UserRoleRelationships" lazy="true">
<key>
<column name="RoleId"/>
</key>
<many-to-many class="domain.IWUser" column="UserId"/>
</set>
</class>
</hibernate-mapping>
How can I get hibernate to save the new user with an existing user role in the join table?
Problem #2:
When I update the user, hibernate delete the relations in the join table. How can I avoid this?
How can I get hibernate to save the new user with an existing user role in the join table?
Retrieve the user role entity and put that into the list instead of always creating a new one.
I mean this part:
IWUserRole iwUserRole = new IWUserRole();
iwUserRole.setRole("ROLE_USER");
Instead, you'd issue a query like select r from IWUserRole where r.role = 'ROLE_USER'