#IdClass with non primative #Id - java

I'm trying to add a composite primary key to a class and having a bit of trouble. Here are the classes.
class User {
private long id;
...
}
class Token {
private User user;
private String series;
...
}
I'm using the orm.xml to map the classes because they're actually part of a higher level API that I don't want to depend on JPA - it has a number of implementations.
Here it is:
...
<entity class="User">
<attributes>
<id name="id">
<generated-value strategy="AUTO"/>
</id>
...
</attributes>
</entity>
<entity class="Token">
<id-class class="TokenPK"/>
<attributes>
<id name="series"/>
<id name="user"/>
<many-to-one name="user"/>
</attributes>
</entity>
Finally to make it all work, I've created the TokenPK class and it looks like this:
public class TokenPK implements Serializable {
private String series;
private User user;
public TokenPK() {
}
public TokenPK(String series, User user) {
this.series = series;
this.user = user;
}
public String getSeries() {
return series;
}
public void setSeries(String series) {
this.series = series;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RememberMeTokenPK that = (TokenPK) o;
if (!series.equals(that.series)) return false;
if (!user.equals(that.user)) return false;
return true;
}
#Override
public int hashCode() {
int result = series.hashCode();
result = 31 * result + user.hashCode();
return result;
}
}
The problem I'm having is that Hibernate is complaning that it can't create the mysql tables because 'BLOB/TEXT column 'user' used in key specification without a key length'.
My issue is actually that the columns are being stored as BLOBs in the first place. Until I put the id-class in it was working just fine, user was linked via it's id. How can I make Hibernate use the long value for the user's id it was using as the primary key?
Updated orm.xml:
<entity class="Token">
<id-class class="TokenPK"/>
<attributes>
<id name="series"/>
<id name="user">
<column name="userId"/>
</id>
<many-to-one name="user">
<join-column name="userId" insertable="false" updatable="false"/>
</many-to-one>
</attributes>
</entity>

Define the composite key with String series and int userId, and specify a join-column id for the User in Token. I think you will also have to add insertable="false", updatable="false".
<composite-id name="TikenPK" class="yourpackage.TokenPK">
<key-property name="series" column="series" type="string" />
<key-property name="userId" column="userId" type="integer"/>
</composite-id>

Related

Hibernate: How to write Join queries including multi levels?

I am trying to write a HQL Query, which is similar to a MySQL Join. Below are my entities. As you can see below I am not using annotations in my Pojos. Instead I am using XML to do the mapping.
Stock
public class Stock implements java.io.Serializable {
private Integer idstock;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Product product;
private int quantity;
private Date dateCreated;
private Date lastUpdated;
public Stock() {
}
public Stock(Product product, int quantity) {
this.product = product;
this.quantity = quantity;
}
public Stock(Product product, int quantity, Date dateCreated, Date lastUpdated) {
this.product = product;
this.quantity = quantity;
this.dateCreated = dateCreated;
this.lastUpdated = lastUpdated;
}
public Integer getIdstock() {
return this.idstock;
}
public void setIdstock(Integer idstock) {
this.idstock = idstock;
}
public Product getProduct() {
return this.product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getQuantity() {
return this.quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Date getDateCreated() {
return this.dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public Date getLastUpdated() {
return this.lastUpdated;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
}
Product
public class Product implements java.io.Serializable {
private Integer idproduct;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private SparePart sparePart;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private VehicleModel vehicleModel;
private double unitPrice;
private String qrcode;
private boolean enable;
private Integer minimumStockLevel;
private Integer stockReorderLevel;
public Product() {
}
public Product(SparePart sparePart, VehicleModel vehicleModel, double unitPrice, String qrcode, boolean enable) {
this.sparePart = sparePart;
this.vehicleModel = vehicleModel;
this.unitPrice = unitPrice;
this.qrcode = qrcode;
this.enable = enable;
}
public Product(SparePart sparePart, VehicleModel vehicleModel, double unitPrice, String qrcode, boolean enable, Integer minimumStockLevel, Integer stockReorderLevel) {
this.sparePart = sparePart;
this.vehicleModel = vehicleModel;
this.unitPrice = unitPrice;
this.qrcode = qrcode;
this.enable = enable;
this.minimumStockLevel = minimumStockLevel;
this.stockReorderLevel = stockReorderLevel;
}
public Integer getIdproduct() {
return this.idproduct;
}
public void setIdproduct(Integer idproduct) {
this.idproduct = idproduct;
}
public SparePart getSparePart() {
return this.sparePart;
}
public void setSparePart(SparePart sparePart) {
this.sparePart = sparePart;
}
public VehicleModel getVehicleModel() {
return this.vehicleModel;
}
public void setVehicleModel(VehicleModel vehicleModel) {
this.vehicleModel = vehicleModel;
}
public double getUnitPrice() {
return this.unitPrice;
}
public void setUnitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
public String getQrcode() {
return this.qrcode;
}
public void setQrcode(String qrcode) {
this.qrcode = qrcode;
}
public boolean getEnable() {
return this.enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public Integer getMinimumStockLevel() {
return this.minimumStockLevel;
}
public void setMinimumStockLevel(Integer minimumStockLevel) {
this.minimumStockLevel = minimumStockLevel;
}
public Integer getStockReorderLevel() {
return this.stockReorderLevel;
}
public void setStockReorderLevel(Integer stockReorderLevel) {
this.stockReorderLevel = stockReorderLevel;
}
}
VehicleModel
public class VehicleModel implements java.io.Serializable {
private Integer idvehicleModel;
private String modelName;
private String code;
private boolean enable;
public VehicleModel() {
}
public VehicleModel(String modelName, boolean enable) {
this.modelName = modelName;
this.enable = enable;
}
public Integer getIdvehicleModel() {
return this.idvehicleModel;
}
public void setIdvehicleModel(Integer idvehicleModel) {
this.idvehicleModel = idvehicleModel;
}
public String getModelName() {
return this.modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public boolean getEnable() {
return this.enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
SparePart
public class SparePart implements java.io.Serializable {
private Integer idsparePart;
private String sparePartName;
private String code;
private boolean enable;
public SparePart() {
}
public SparePart(String sparePartName, boolean enable) {
this.sparePartName = sparePartName;
this.enable = enable;
}
public Integer getIdsparePart() {
return this.idsparePart;
}
public void setIdsparePart(Integer idsparePart) {
this.idsparePart = idsparePart;
}
public String getSparePartName() {
return this.sparePartName;
}
public void setSparePartName(String sparePartName) {
this.sparePartName = sparePartName;
}
public boolean getEnable() {
return this.enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
Here are my XML mappings
Product.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.Product" table="product" catalog="aaa" optimistic-lock="version">
<id name="idproduct" type="java.lang.Integer">
<column name="idproduct" />
<generator class="identity" />
</id>
<many-to-one name="sparePart" class="beans.SparePart" fetch="select">
<column name="idspare_part" not-null="true" />
</many-to-one>
<many-to-one name="vehicleModel" class="beans.VehicleModel" fetch="select">
<column name="idvehicle_model" not-null="true" />
</many-to-one>
<property name="unitPrice" type="double">
<column name="unit_price" precision="22" scale="0" not-null="true">
<comment>This is the central price for a product. This can change according to the market values.</comment>
</column>
</property>
<property name="qrcode" type="string">
<column name="qrcode" length="45" not-null="true" />
</property>
<property name="enable" type="boolean">
<column name="enable" not-null="true" />
</property>
<property name="minimumStockLevel" type="java.lang.Integer">
<column name="minimum_stock_level" />
</property>
<property name="stockReorderLevel" type="java.lang.Integer">
<column name="stock_reorder_level" />
</property>
</class>
</hibernate-mapping>
Stock.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.Stock" table="stock" catalog="aaa" optimistic-lock="version">
<id name="idstock" type="java.lang.Integer">
<column name="idstock" />
<generator class="identity" />
</id>
<many-to-one name="product" class="beans.Product" fetch="select">
<column name="idproduct" not-null="true" />
</many-to-one>
<property name="quantity" type="int">
<column name="quantity" not-null="true" />
</property>
<property name="dateCreated" type="timestamp">
<column name="date_created" length="0" />
</property>
<property name="lastUpdated" type="timestamp">
<column name="last_updated" length="0" />
</property>
</class>
</hibernate-mapping>
SparePart.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.SparePart" table="spare_part" catalog="aaa" optimistic-lock="version">
<id name="idsparePart" type="java.lang.Integer">
<column name="idspare_part" />
<generator class="identity" />
</id>
<property name="sparePartName" type="string">
<column name="spare_part_name" length="100" not-null="true" />
</property>
<property name="code" type="string">
<column name="code" length="100"/>
</property>
<property name="enable" type="boolean">
<column name="enable" not-null="true" />
</property>
</class>
</hibernate-mapping>
VehicleModel.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 4, 2020 1:35:36 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="beans.VehicleModel" table="vehicle_model" catalog="aaa" optimistic-lock="version">
<id name="idvehicleModel" type="java.lang.Integer">
<column name="idvehicle_model" />
<generator class="identity" />
</id>
<property name="modelName" type="string">
<column name="model_name" length="100" not-null="true" />
</property>
<property name="code" type="string">
<column name="code" length="100"/>
</property>
<property name="enable" type="boolean">
<column name="enable" not-null="true" />
</property>
</class>
</hibernate-mapping>
Right now I have the following query.
public List<Stock> getAllStock(Session session) {
Query query = session.createQuery("FROM Stock s");
List<Stock> list = (List<Stock>) query.list();
return list;
}
This gives me,
Stock
Product of each Stock
SparePart of each Product
VehicleModel of each Product
However this is extremely slow due to the famous n+1 issue. To get data from each table, this code generated a SQL query, resulting huge amount of sql queries. The more data you have, the more queries this generates . As a result, this is a super slow process. Currently it takes 40 seconds.
Instead I need to write HQL joins and get data with a single SQL query. How can I do this?
You should use JOIN FETCH to tell JPA/Hibernate that that it should load it.
From the Hibernate docs:
If you forget to JOIN FETCH all EAGER associations, Hibernate is going
to issue a secondary select for each and every one of those which, in
turn, can lead to N+1 query issues.
For this reason, you should prefer LAZY associations.
select s from Stock s join fetch s.product p
join fetch p.sparePart sp
join fetch p.vehicleModel v
Please also read the documentation: https://docs.jboss.org/hibernate/orm/5.5/userguide/html_single/Hibernate_User_Guide.html#best-practices-fetching-associations
You can use criteria implementation of hibernate and using alias you can join
Below is some reference code that may help
Criteria c = session.createCriteria(Stock.class, "stock");
c.createAlias("stock.product", "product");//it is like inner join
c.createAlias("product.spare_part","spare_part");
c.createAlias("product.vehicle_model","vehicle_model");
return c.list();

Repeated column in mapping for entity in hibernate XML mapping

I have been facing an issue of "Repeated column in mapping for entity". Could you kindly help me where i have done mistake on it. I have mentioned my code below.
USERAUDIT.hbm.xml
<hibernate-mapping>
<class name="com.mkyong.user.UserAudit" table="USER_AUDIT_TBL">
<id name="eventId" column="EVENT_ID" type="java.lang.Integer">
<generator class="sequence">
<param name="sequence">AUDIT_SEQUENCE</param>
</generator>
</id>
<property name="userId" type="java.lang.Integer">
<column name="USER_ID" length="10" not-null="true" unique="true" />
</property>
<set name="userAuditDtls" table="USER_AUTI_DTLS_TBL" inverse="true"
lazy="true" fetch="select">
<key>
<column name="EVENT_ID" not-null="true" />
</key>
<one-to-many class="com.mkyong.user.UserAuditDtls" />
</set>
</class>
</hibernate-mapping>
USERAUDIT.java
enter code herepublic class UserAudit implements java.io.Serializable {
private Integer eventId;
private Integer userId;
//private UserAuditDtls userAuditDtls;
private Set<UserAuditDtls> userAuditDtls =
new HashSet<UserAuditDtls>(0);
public UserAudit(Integer eventId, Integer userId, Set<UserAuditDtls> userAuditDtls) {
super();
this.eventId = eventId;
this.userId = userId;
this.userAuditDtls = userAuditDtls;
}
public UserAudit() {
super();
// TODO Auto-generated constructor stub
}
public Integer getEventId() {
return eventId;
}
public void setEventId(Integer eventId) {
this.eventId = eventId;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Set<UserAuditDtls> getUserAuditDtls() {
return userAuditDtls;
}
public void setUserAuditDtls(Set<UserAuditDtls> userAuditDtls) {
this.userAuditDtls = userAuditDtls;
}
}
USERAUDITDTLS.hbm.xml
<hibernate-mapping>
<class name="com.mkyong.user.UserAuditDtls" table="PII_USER_AUTI_DTLS_TBL">
<id name="eventId" type="java.lang.Integer">
<column name="EVENT_ID" />
<generator class="foreign">
<param name="property">userAudit</param>
</generator>
</id>
<many-to-one name="userAudit" class="com.mkyong.user.UserAudit" fetch="select">
<column name="EVENT_ID" not-null="true" />
</many-to-one>
<property name="fieldName" type="string">
<column name="FIELD_NAME" length="100" not-null="true" />
</property>
</class>
</hibernate-mapping>
UserAuditDtls.java
public class UserAuditDtls implements java.io.Serializable {
private Integer eventId;
private UserAudit userAudit;
private String fieldName;
public UserAuditDtls() {
super();
// TODO Auto-generated constructor stub
}
public UserAuditDtls(Integer eventId, UserAudit userAudit, String fieldName) {
super();
this.eventId = eventId;
this.userAudit = userAudit;
this.fieldName = fieldName;
}
public Integer getEventId() {
return eventId;
}
public void setEventId(Integer eventId) {
this.eventId = eventId;
}
public UserAudit getUserAudit() {
return userAudit;
}
public void setUserAudit(UserAudit userAudit) {
this.userAudit = userAudit;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
}
Main.Java
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
UserAudit audit = new UserAudit();
audit.setUserId(new Integer(100));
session.save(audit);
UserAuditDtls auditDtls = new UserAuditDtls();
auditDtls.setFieldName("Small");
auditDtls.setUserAudit(audit);
audit.getUserAuditDtls().add(auditDtls);
session.save(auditDtls);
session.getTransaction().commit();
Error:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.mkyong.user.UserAuditDtls column: EVENT_ID (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:676)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:698)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:720)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:474)
at org.hibernate.mapping.RootClass.validate(RootClass.java:235)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1335)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1838)
at com.mkyong.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:13)
Tables:
USER_AUDIT_TBL
event_id - pk
userid -integer
USER_AUDIT_DTLS_TBL
event_id- fk
fieldname - varchar
problem is <column name="EVENT_ID" not-null="true" /> in USERAUDITDTLS.hbm.xml

could not initialize proxy - no Session (Spring-Hibernate-one to one)

I have two tabeles and I want to fetch on update data from database.
users table(columns):
user_id - username - password - role_id(Foreign Key) - email
user_roles table(columns):
role_id - role
I want to list users in users.jsp . lets see my codes:
User.java
package com.terafast.manager.model;
public class User {
private int id;
private String username;
private String password;
private String email;
private Role role;
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
Role.java
package com.terafast.manager.model;
public class Role {
private int id;
private String role;
public Role() {
}
public Role(String role) {
this.role = role;
}
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
User.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.terafast.manager.model">
<class name="User" table="users">
<id name="id" column="USER_ID">
<generator class="native" />
</id>
<property name="username" column="USERNAME" />
<property name="password" column="PASSWORD" />
<property name="email" column="EMAIL" />
<many-to-one name="Role" class="com.terafast.manager.model.Role"
unique="true" not-null="true" column="role_id" />
</class>
</hibernate-mapping>
Role.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.terafast.manager.model">
<class name="Role" table="user_roles">
<id name="id" column="role_id">
<generator class="native" />
</id>
<property name="role" />
</class>
</hibernate-mapping>
This part is from UserDAOImpl that create List of users:
#Override
#Transactional
public List<User> list() {
#SuppressWarnings("unchecked")
List<User> listUser = (List<User>) sessionFactory.getCurrentSession().createCriteria(User.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
return listUser;
}
I already declared public List list(); in UserDAO interface.
This is the part that I send List of users to users.jsp from my Controller:
#RequestMapping("/users/show")
public ModelAndView handleRequest() throws Exception {
List<User> listUsers = userDao.list();
ModelAndView model = new ModelAndView("panel/users");
model.addObject("userList", listUsers);
return model;
}
In jsp file I list Users like this:
<c:forEach var="user" items="${userList}" varStatus="status">
<tr>
<td>${status.index + 1}</td>
<td>${user.username}</td>
<td>${user.email}</td>
<td>${user.role}</td>
<td>Edit
Delete
</td>
</tr>
</c:forEach>
So when I run this project as server I got this output:
Hibernate: select this_.USER_ID as USER_ID1_1_0_, this_.USERNAME as USERNAME2_1_0_, this_.PASSWORD as PASSWORD3_1_0_, this_.EMAIL as EMAIL4_1_0_, this_.role_id as role_id5_1_0_ from users this_
and then this error:
Jul 20, 2015 3:32:06 PM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet jsp threw exception
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Could someone explain what is wrong with my program? And how can if I want to add or edit user, what should I do exactly?
By default, all associations are lazy in Hibernate (as opposed to JPA where to-one associations are eager by default).
Either make the association between User and Role eager (lazy="false"):
<many-to-one name="Role" class="com.terafast.manager.model.Role"
lazy="false" unique="true" not-null="true" column="role_id" />
or explicitly initialize the lazy associations which you intend to use out of the session boundaries:
#SuppressWarnings("unchecked")
List<User> listUser = (List<User>) sessionFactory.getCurrentSession().createCriteria(User.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
for (User user : listUser) {
Hibernate.initialize(user.getRole());
}
Then in users.jsp, you should use ${user.role.role} to access the value.
Your exception totally depends on Lazy and Eager loading.
Set the <many-to-one> relation with property of lazy with false in your user.hbm.xml file.
try this:
<many-to-one name="Role" class="com.terafast.manager.model.Role"
lazy="false" fetch="select" unique="true" not-null="true" column="role_id" />
and follow #Dragan Bozanovic answer.

How to handle Many-To-Many Relation with existed data in Hibernate

I had three table i.e,personalinfo,groups_designation,groups_desig_category
personalinfo:pid(personal id)
groups_designation:gid(group id)
groups_desig_category:gid,pid
Actually I have data in both table's (personalinfo,groups_designation).So we have provide one screen.In that,The user selects the group and assign personal id and the data pulled into groups_desig_category table.In this scenario,i mapped like
Personal.hbm.xml:-
<set name="empwthgrp" inverse="true" lazy="true" table="groups_desig_category">
<key>
<column name="pid" not-null="true" />
</key>
<many-to-many entity-name="com.aims.beans.DesignationGroupBean">
<column name="gid" not-null="true" />
</many-to-many>
</set>
Personal.java:-
/**
*
*/
private static final long serialVersionUID = 1L;
private int pid,deptno;
private String name,designation;
private Address address;
private Address permentaddress;
private Set famildtlslst;
private Set empwthgrp=new HashSet();
public Set getEmpwthgrp() {
return empwthgrp;
}
public void setEmpwthgrp(Set empwthgrp) {
this.empwthgrp = empwthgrp;
}
public Set getFamildtlslst() {
return famildtlslst;
}
public void setFamildtlslst(Set famildtlslst) {
this.famildtlslst = famildtlslst;
}
public Address getPermentaddress() {
return permentaddress;
}
public void setPermentaddress(Address permentaddress) {
this.permentaddress = permentaddress;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
GroupingDesig.hbm.xml:-
<class name="beans.DesignationGroupBean" table="groups_designation" proxy=beans.DesignationGroupBean">
<id name="gid" column="gid" type="java.lang.Integer">
<generator class="sequence"><param name="sequence">gid_seq</param> </generator>
</id>
<property name="gname" type="java.lang.String" column="gname" not-null="true" />
<property name="description" type="java.lang.String" column="description" not-null="true" />
<set name="grpwthemp" inverse="true" lazy="true" table="groups_desig_category">
<key>
<column name="gid" not-null="true" />
</key>
<many-to-many entity-name="com.aims.beans.Personal">
<column name="pid" not-null="true" />
</many-to-many>
</set>
</class>
DesignationGroupBean.java:-
private int gid;
private String gname,description;
private Set grpwthemp=new HashSet();
public Set getGrpwthemp() {
return grpwthemp;
}
public void setGrpwthemp(Set grpwthemp) {
this.grpwthemp = grpwthemp;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getGid() {
return gid;
}
public void setGid(int gid) {
this.gid = gid;
}
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
Actually I trying session.saveOrUpdate(pBean).But its not working.May be can change one-to many and many-to-one instead of many-to-many relation.I think it is not suitable in this scenario.So,How to handle in this scenario?.If you using reverse engineering then it created as one-to-many and many-to-one relation? why?.Please help me.
Update:-
I am implemented in one-to-many and many-to-one relation hibernate whereas in database its many-to-many relation.then Its working fine and below pasted the hibernate mapping files with one-to-many relation ship
GroupingDesig.hbm.xml:-
<set name="grpwthemp" inverse="true" lazy="true" table="groups_desig_category">
<key>
<column name="gid" not-null="true" />
</key>
<one-to-many class="com.aims.beans.GroupAssignment"/>
<!-- <many-to-many entity-name="com.aims.beans.Personal">
<column name="pid" not-null="true" />
</many-to-many>-->
</set>
Personal.hbm.xml
<set name="empwthgrp" inverse="true" lazy="true" table="groups_desig_category">
<key>
<column name="pid" not-null="true" />
</key>
<one-to-many class="com.aims.beans.GroupAssignment"/>
<!--
<many-to-many entity-name="com.aims.beans.DesignationGroupBean">
<column name="gid" not-null="true" />
</many-to-many>-->
</set>
AssigGroupingDesig.hbm.xml:-
<many-to-one name="personal" column="pid" class="com.aims.beans.Personal" not-null="true"></many-to-one>
<many-to-one name="desigdt" column="gid" class="com.aims.beans.DesignationGroupBean" not-null="true"></many-to-one>
When will be came picture the relation ship?.I have search many-to-many relation example's in web i.e,.
Mykong many-to-many
Please help me.My Question is when will be came/used many-to-many relation ship in real time?.
Update 2:-
Thanks.Removing the inverse tag its working fine.But i have doubt regarding generation of deleting the query.Please check the logs
/* load com.beans.Personal */ select personal0_.pid as pid0_, personal0_.name as name5_0_, personal0_.DEPTNO as DEPTNO5_0_, personal0_.designation as designat4_5_0_, personal0_.pddress1 as pddress5_5_0_, personal0_.pddress2 as pddress6_5_0_, personal0_.pcity as pcity5_0_, personal0_.pstate as pstate5_0_, personal0_1_.HomeAddress1 as HomeAddr2_7_0_, personal0_1_.HomeAddress2 as HomeAddr3_7_0_, personal0_1_.homecity as homecity7_0_, personal0_1_.homestate as homestate7_0_ from personalinfo personal0_, address personal0_1_ where personal0_.pid=personal0_1_.pid and personal0_.pid=?
delete collection com.beans.Personal.empwthgrp */ delete from groups_desig_category where pid=?
insert collection row com.beans.Personal.empwthgrp */ insert into groups_desig_category (pid, gid) values (?, ?)
why generating the "delete from groups_desig_category where pid=?".Plz help me
Update 3:-
Yes.Iam loading the data using session.get.becuase i got exception regarding the some of mandatory fields.that is reason i loaded the data then update the records
per=(Personal)session.get(Personal.class,new Integer(pBean.getPid()));
per.setEmpwthgrp(pBean.getEmpwthgrp());
session.saveOrUpdate(per);
In your many-to-many mappings, you set both of them to inverse. You need to choose one entity that will own the relationship - for that one, in the mapping, you will remove the inverse="true" setting. That will be the entity that, when saved or updated, will persist the person to group relationship.
Since in your question you posted saveOrUpdate(pBean), and I assume pBean is Personal entity, then you need to remove the inverse="true" setting in Personal.hbm.xml.
More info in the reference documentation: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/associations.html#assoc-bidirectional-join-m2m

Hibernate bidirectional parent/child problem

I'm having a problem implementing a bi-directional parent/child relationship using hibernate 3. The parent, in this case is of the class ReportCriteria. The child is of class PkVisit. I've pasted my hibernate configuration files as well as the underlying java objects below.
ReportCriteria configuration:
<hibernate-mapping package="org.fstrf.masterpk.domain">
<class name="ReportCriteriaBean" table="masterPkReportCriteria">
<id name="id" column="id">
<generator class="org.hibernate.id.IncrementGenerator" />
</id>
<bag name="pkVisits" table="masterPkWeeks" cascade="all-delete-orphan" inverse="true">
<key column="runId"/>
<one-to-many class="PkVisit"/>
</bag>
</class>
</hibernate-mapping>
ReportCriteria bean:
public class ReportCriteriaBean {
private Integer id;
private List<PkVisit> pkVisits = LazyList.decorate(new ArrayList(), FactoryUtils.instantiateFactory(PkVisit.class));
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<PkVisit> getPkVisits() {
return pkVisits;
}
public void setPkVisits(List<PkVisit> pkVisits) {
this.pkVisits = pkVisits;
}
}
PkVisit Configuration:
<hibernate-mapping package="org.fstrf.masterpk.domain">
<class name="PkVisit" table="masterPkWeeks">
<id name="id" column="id">
<generator class="org.hibernate.id.IncrementGenerator" />
</id>
<many-to-one name="reportCriteriaBean" class="ReportCriteriaBean" column="runid" not-null="true" />
<property name="week" column="week" />
</class>
</hibernate-mapping>
PkVisit Bean:
public class PkVisit {
private Integer id;
private ReportCriteriaBean reportCriteriaBean;
private Integer week;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public ReportCriteriaBean getReportCriteriaBean() {
return reportCriteriaBean;
}
public void setReportCriteriaBean(ReportCriteriaBean reportCriteriaBean) {
this.reportCriteriaBean = reportCriteriaBean;
}
public Integer getWeek() {
return week;
}
public void setWeek(Integer week) {
this.week = week;
}
}
The problem occurs when I try to save an instance of ReportCriteria, which, due to the cascade should also save any child PkVisits as well. However, when the save is called using
hibernateTemplate.saveOrUpdate(reportCriteria);
The following error is generated:
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: org.fstrf.masterpk.domain.PkVisit.reportCriteriaBean; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: org.fstrf.masterpk.domain.PkVisit.reportCriteriaBean
When I save a report criteria that contains no PkVisits then everything works as I would expect, but as soon as any elements are in the pkVisits list of the ReportCriteria bean the errors occurs.
SOLUTION EDIT:
My problem was that I was never explicitly setting the parent (ReportCriteriaBean) in the children (PkVisits). I remedied the problem by editing my PkVisits setter in the following way:
public void setPkVisits(List<PkVisit> pkVisits) {
this.pkVisits = pkVisits;
for(PkVisit visit : pkVisits){
visit.setReportCriteriaBean(this);
}
}
It appears that you are not creating the bidirectional link in java properly. I'd recommend creating an add method on ReportCriteriaBean; something to the effect of:
public boolean add(PkVisit pkVisit) {
boolean added = false;
added = getPkVisits().add(pkVisit);
if (added) {
pkVisit.setReportCriteriaBean(this);
}
return added;
}
The error indicates that you cannot save a PkVisit if its ReportCriteriaBean is null. The above code, i think, is your missing link. If you go this route, you just add the PkVisit to the ReportCriteriaBean before persisting the report criteria and all should be well.
Also, here's a link to the hibernate documentation on this subject, section 21.2
Check if the PkVisit is generated ok, prior to the saveOrUpdate() call.
Then, you may need to eager fetch reportCriteriaBean/pkVisits where you have the hibernate session, prior to accessing them where you don't have hibernate session:
Hibernate.initialize(reportCriteriaBean.getPkVisits());

Categories

Resources