What is the equivalent way of defining dynamic component in hibernate by annotations?
public abstract class CustomizableEntity {
private Map customProperties;
public Map getCustomProperties() {
if (customProperties == null)
customProperties = new HashMap();
return customProperties;
}
public void setCustomProperties(Map customProperties) {
this.customProperties = customProperties;
}
public Object getValueOfCustomField(String name) {
return getCustomProperties().get(name);
}
public void setValueOfCustomField(String name, Object value) {
getCustomProperties().put(name, value);
}
}
my entity:
public class Contact extends CustomizableEntity {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
hibernate xml:
<hibernate-mapping auto-import="true" default-access="property" default-cascade="none" default-lazy="true">
<class abstract="false" name="com.enterra.customfieldsdemo.domain.Contact" table="tbl_contact">
<id column="fld_id" name="id">
<generator class="native"/>
</id>
<property name="name" column="fld_name" type="string"/>
<dynamic-component insert="true" name="customProperties" optimistic-lock="true" unique="false" update="true">
</dynamic-component>
</class>
</hibernate-mapping>
I want to use a dynamic-component by HashMap to create entities at runtime.
What is the equivalent way of defining dynamic component in hibernate by annotations?
http://www.infoq.com/articles/hibernate-custom-fields
Related
I have two tables - Student and Address. They have one to many relationship. Student entity is having collection of address entity. When i updating collection of address in student. Its not updating the data and giving this error. When i was updating the parent entity with child collection, its taking next to be incremented key which is not in the database. -
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:124)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:189)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:59)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3079)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3521)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:395)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:387)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:303)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:349)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1195)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at com.HibernateExample.test.HibernateTest.main(HibernateTest.java:51)
Caused by: org.postgresql.util.PSQLException: ERROR: insert or update on table "address" violates foreign key constraint "student_fk"
Detail: Key (id)=(5) is not present in table "student".
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2476)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2189)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:186)
... 14 more
Student.java
public class Student {
public int id;
public String firstName;
public String lastName;
public int age;
public Set<Address> address = new HashSet<>(0);
public Set<Address> getAddress() {
return address;
}
public void setAddress(Set<Address> address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Address.java
public class Address {
public int id;
public String streetName;
public String cityName;
public String stateName;
public String plotNo;
public Student student;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public String getPlotNo() {
return plotNo;
}
public void setPlotNo(String plotNo) {
this.plotNo = plotNo;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
HibernateTest.java
public class HibernateTest {
public static void main(String[] args) {
Configuration configuration = new Configuration();
configuration.configure("hibernate-cfg.xml");
#SuppressWarnings("deprecation")
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.COMMIT);
System.out.println(session.getFlushMode().name());
Transaction transaction = session.beginTransaction();
Student student = (Student) session.get(Student.class, 3);
Address address = new Address();
address.setStateName("Kerala");
address.setCityName("Old Delhi");
address.setStreetName("Uttaam Nagar");
address.setPlotNo("158A");
address.setStudent(student);
student.getAddress().add(address);
session.update(student);
transaction.commit();
session.close();
sessionFactory.close();
}
}
address.hbm.xml
<hibernate-mapping>
<class name="com.HibernateExample.entity.Address" table="address">
<meta attribute="class-description">
This class contains the address detail.
</meta>
<id name="id" type="int" column="id">
<generator class="increment" />
</id>
<property name="streetName" column="street_name" type="string"/>
<property name="cityName" column="city_name" type="string"/>
<property name="stateName" column="state_name" type="string"/>
<property name="plotNo" column="plot_no" type="string"/>
<many-to-one name="student" class="com.HibernateExample.entity.Student" >
<column name="student_id" not-null="true"></column>
</many-to-one>
</class>
</hibernate-mapping>
student.hbm.xml
<hibernate-mapping>
<class name="com.HibernateExample.entity.Student" table="student">
<meta attribute="class-description">
This class contains the student detail.
</meta>
<id name="id" type="int" column="id">
<generator class="increment" />
</id>
<property name="firstName" column="first_name" type="string" length="40" />
<property name="lastName" column="last_name" type="string" length="40" />
<property name="age" column="age" type="int"/>
<set name="address" cascade="all">
<key column="student_id"/>
<one-to-many class="com.HibernateExample.entity.Address"/>
</set>
</class>
</hibernate-mapping>
From the Session javadoc, Session.update() is specified to work with a detached entity instance. "If there is a persistent instance with the same identifier, an exception is thrown." Exactly which exception is not specified, and cascading might send it down a complex code path, which could result in this error.
The Student object you modify is not detached, but rather persistent, because you got it by loading from the Session and have not closed the Session or done anything else that would detach it. This means that all modifications to it are saved to the database automatically, with no need for any manual call on Session. This is specified in the class javadoc for Session, with the sentence "Changes to persistent instances are detected at flush time and also result in an SQL UPDATE."
Simply delete the line session.update(student);, and I think your code will start working, including saving the new address through the cascaded relationship when you commit the transaction.
It's been a while since I've worked with cascades so I'm not entirely certain, but you might also need to set cascade on the other side of the relationship.
The "student_id" is not associated with any of your primary keys. If "student_id" exists in both Student and Address tables then change this line in your student mapping file from "id" to "student_id":
<id name="id" type="int" column="student_id">
Double check your database table with a database table viewer/browser.
It seems you try to insert an ID that already exists in the database (5)
I have a POJO class NewUniversity.java. I've created a mapping file for it viz. RegisterAction.hbm.xml. Now the problem is when I try to call the save methods from DAO class, only the first one gets executed, the second one doesn't. I've two tables linked to one entity through 'entity-mapping' attribute in the xml file.
File: NewUniversity.java
public class NewUniversity implements Serializable {
// University fields
private String uCode;
private String uName;
private String uAddress;
private String uCity;
private String uState;
private long uContactNo;
private String uEmail;
// University director fields
private String name;
private String address;
private String city;
private String state;
private long contactNo;
private String email;
private String userName;
private String pwd;
public String getuCode() {
return uCode;
}
public void setuCode(String uCode) {
this.uCode = uCode;
}
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public String getuAddress() {
return uAddress;
}
public void setuAddress(String uAddress) {
this.uAddress = uAddress;
}
public String getuCity() {
return uCity;
}
public void setuCity(String uCity) {
this.uCity = uCity;
}
public String getuState() {
return uState;
}
public void setuState(String uState) {
this.uState = uState;
}
public long getuContactNo() {
return uContactNo;
}
public void setuContactNo(long uContactNo) {
this.uContactNo = uContactNo;
}
public String getuEmail() {
return uEmail;
}
public void setuEmail(String uEmail) {
this.uEmail = uEmail;
}
// University directors setters/getters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public long getContactNo() {
return contactNo;
}
public void setContactNo(long contactNo) {
this.contactNo = contactNo;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
File: RegisterAction.hbm.xml
<?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>
<class name="in.ryr.register.NewUniversity" table="university"
entity-name="university">
<id name="uCode" column="code" type="string">
<generator class="assigned" />
</id>
<property name="uName" column="name" />
<property name="uAddress" column="address" />
<property name="uCity" column="city" />
<property name="uState" column="state" />
<property name="uContactNo" column="contact_no" />
<property name="uEmail" column="email" />
<property name="userName" column="username" />
</class>
<class name="in.ryr.register.NewUniversity" table="university_director"
entity-name="uniDirector">
<id name="userName" column="username" type="string">
<generator class="assigned" />
</id>
<property name="name" column="name" />
<property name="address" column="address" />
<property name="city" column="city" />
<property name="state" column="state" />
<property name="contactNo" column="contact_no" />
<property name="email" column="email" />
<property name="pwd" column="password" />
<property name="uCode" column="u_code" />
</class>
</hibernate-mapping>
File: RegisterDAO.java
public void register(NewUniversity user) throws Exception {
session = factory.openSession();
transaction = session.beginTransaction();
try {
session.save("university", user); //This is working fine
session.save("uniDirector", user); //This doesn't execute at all
transaction.commit();
session.close();
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
session.close();
}
}
I've tried using persist() as well. But no luck!
The point is, when I perform it on two different sessions, it works perfectly. (All the objects value are coming through .jsp to struts). For some reasons I didn't use annotations.
Maybe it is because Session#save(entityName, object) method requires object to be a "transient" object (i.e. that has not already been persisted), and that, after the first call to session.save("university", user); then user is no more transient.
Persist the given transient instance, first assigning a generated
identifier. (Or using the current value of the identifier property if
the assigned generator is used.) This operation cascades to associated
instances if the association is mapped with cascade="save-update"
What happens when you make a get of your persisted "university" entity just after the first save, and then save it as "uniDirector" ?
I am trying to use Hibernate but when I execute a query I receive a list of my entity where all the attributes are NULL. The thing is that when i use the jdbc directly I am able to retrieve the values from my Db.
I read similar articles about NULL values but couldn't figure out what s wrong in my case.
Below you see:
1) My entity: Eshop
public class Eshop implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public Eshop() {}
public Eshop(int eshopId, String code, String name, String lastModified) {
this.eshopId = eshopId;
this.code = code;
this.name = name;
this.lastModified = lastModified;
}
public int eshopId;
public String code;
public String name;
public String lastModified;
public int getEshopId() {
return eshopId;
}
public void setEshopId(int eshopId) {
eshopId = eshopId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
name = name;
}
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
lastModified = lastModified;
}
2) The Hibernate Mapping
<hibernate-mapping>
<class name="dataModel.Eshop" table="Eshop">
<meta attribute="class-description">
This class contains the Eshop details.
</meta>
<id name="eshopId" type="int" column="EshopId">
<generator class="native"/>
</id>
<property name="code" column="Code" type="string"/>
<property name="name" column="Name" type="string"/>
<property name="lastModified" column="LastModified" type="string"/>
</class>
</hibernate-mapping>
And this is how I run the query:
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query hibernateQuery = session.createQuery("from Eshop");
List<Eshop> Eshops = hibernateQuery.list();
So when I run a query i receive the exact number of Eshops which are in my Db but all their attributes values are null!!
An ideas?? Thank you
All your setters are wrong:
public void setEshopId(int eshopId) {
eshopId = eshopId;
}
This is a noop. It should be
public void setEshopId(int eshopId) {
this.eshopId = eshopId;
}
Try to add hibernate.cfg.xml like this:
Configuration config = new Configuration().configure("hibernate.cfg.xml");
I have three classes
Student.java
public class Student {
long id;
String name;
Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
Address.java
public class Address {
String houseNumber;
String addrLine1;
String addrLine2;
String phone;
public String getHouseNumber() {
return houseNumber;
}
public void setHouseNumber(String houseNumber) {
this.houseNumber = houseNumber;
}
public String getAddrLine1() {
return addrLine1;
}
public void setAddrLine1(String addrLine1) {
this.addrLine1 = addrLine1;
}
public String getAddrLine2() {
return addrLine2;
}
public void setAddrLine2(String addrLine2) {
this.addrLine2 = addrLine2;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
Hibernate Mapping for Student.hbm.xml
Student.hbm.xml
<?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>
<class name="Student" table="STUDENT">
<id name="id" type="long" column="ID"/>
<property name="name" column="NAME"/>
<component name="address" class="Address">
<property name="houseNumber" column="HOUSE_NUMBER" not-null="true"/>
<property name="addrLine1" column="ADDRLINE1"/>
<property name="addrLine2" column="ADDRLINE2"/>
<property name="phone" column="PHONE"/>
</component>
</component>
</class>
</hibernate-mapping>
Now I want to access the property houseNumber, phone using detached criteria
but when I try to get the property as address.phone
I get the errors as
org.hibernate.QueryException: could not resolve property: phone of: Student
The error occurs because Student really does not have the "phone", which is a Address property.
The correct usage should be something like session.createCriteria( Student.class ).add( Restrictions.eq( "address.phone", "myPhoneNumber" ) ).list() for common criterias.
The version with DetachedCriteria is
DetachedCriteria criteria = DetachedCriteria.forClass( Student.class ).add(Restrictions.eq( "address.phone", "99999999" ) );
List students = criteria.getExecutableCriteria( session ).list();
The hibernate mapping of my hbm.xml is:
<class name="UserCalendar" table="user_calendar">
<id name="userCalendarId" column="user_calendar_id" type="long">
<generator class="native" />
</id>
<property name="userId" column="user_id" type="long" not-null="true"/>
<property name="userLoginName" column="user_login_name" type="string" not-null="true" length="32000" />
<property name="userName" column="user_name" type="string" not-null="true" length="32000" />
<list name="userDates" cascade="all" lazy="false">
<key column="user_calendar_id"/>
<index column="idx"/>
<one-to-many class="UserDate"/>
</list>
</class>
<class name="UserDate" table="user_date">
<id name="userDateId" column="user_date_id" type="long">
<generator class="native" />
</id>
<property name="date" column="date" type="date"/>
<list name="userItems" cascade="all" lazy="false">
<key column="user_date_id"/>
<index column="idx"/>
<one-to-many class="UserItem"/>
</list>
</class>
<class name="UserItem" table="user_item">
<id name="userItemId" column="user_item_id" type="long">
<generator class="native"/>
</id>
<property name="spaceId" column="space_id" type="long"/>
<property name="spaceName" column="space_name" type="string"/>
<property name="itemRefId" column="item_ref_id" type="string"/>
<property name="itemId" column="item_id" type="long"/>
<property name="allocation" column="allocation" type="double"/>
<property name="scheduledStrategy" column="scheduled_strategy" type="integer"/>
<property name="utilization" column="utilization" type="double"/>
<property name="deadline" column="deadline" type="date"/>
<property name="ticketType" column="ticket_type" type="integer"/>
<property name="isCurrentlyAssigned" column="is_currently_assigned" type="boolean"/>
</class>
The UserCalendar.java:
public class UserCalendar implements Serializable {
private static final long serialVersionUID = 10172L;
private long userCalendarId;
private long userId;
private String userLoginName;
private String userName;
private List<UserDate> userDates;
public UserCalendar() {
}
public long getUserCalendarId() {
return userCalendarId;
}
public void setUserCalendarId(long userCalendarId) {
this.userCalendarId = userCalendarId;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserLoginName() {
return userLoginName;
}
public void setUserLoginName(String userLoginName) {
this.userLoginName = userLoginName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<UserDate> getUserDates() {
return userDates;
}
public void setUserDates(List<UserDate> userDates) {
this.userDates = userDates;
}
}
The UserDate.java:
public class UserDate implements Serializable {
private static final long serialVersionUID = 10173L;
private long userDateId;
private Date date;
private List<UserItem> userItems;
public UserDate() {
}
public long getUserDateId() {
return userDateId;
}
public void setUserDateId(long userDateId) {
this.userDateId = userDateId;
}
public void setDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
public List<UserItem> getUserItems() {
return userItems;
}
public void setUserItems(List<UserItem> userItems) {
this.userItems = userItems;
}
}
And the UserItem.java:
public class UserItem implements Serializable {
private static final long serialVersionUID = 10174L;
public static final int AUTO = 1;
public static final int EQUAL = 2;
public static final int CUSTOM = 3;
public static final int CUSTOM_EQUAL = 4;
public static final int GENERAL_TICKET = 5;
public static final int SPECIAL_TICKET_HALF = 6;
public static final int SPECIAL_TICKET_FULL = 7;
private long userItemId;
private long spaceId;
private String spaceName;
private long itemId;
private String itemRefId;
private double allocation;
private int scheduledStrategy;
private double utilization;
private Date deadline;
private int ticketType;
private boolean isCurrentlyAssigned;
public UserItem() {
}
public long getUserItemId() {
return userItemId;
}
public void setUserItemId(long userItemId) {
this.userItemId = userItemId;
}
public long getSpaceId() {
return spaceId;
}
public void setSpaceId(long spaceId) {
this.spaceId = spaceId;
}
public long getItemId() {
return itemId;
}
public void setItemId(long itemId) {
this.itemId = itemId;
}
public double getAllocation() {
return allocation;
}
public void setAllocation(double allocation) {
this.allocation = allocation;
}
public int getScheduledStrategy() {
return scheduledStrategy;
}
public void setScheduledStrategy(int scheduledStrategy) {
this.scheduledStrategy = scheduledStrategy;
}
public double getUtilization() {
return utilization;
}
public void setUtilization(double utilization) {
this.utilization = utilization;
}
public Date getDeadline() {
return deadline;
}
public void setDeadline(Date deadline) {
this.deadline = deadline;
}
public int getTicketType() {
return ticketType;
}
public void setTicketType(int ticketType) {
this.ticketType = ticketType;
}
public String getSpaceName() {
return spaceName;
}
public void setSpaceName(String spaceName) {
this.spaceName = spaceName;
}
public String getItemRefId() {
return itemRefId;
}
public void setItemRefId(String itemRefId) {
this.itemRefId = itemRefId;
}
public boolean isCurrentlyAssigned() {
return isCurrentlyAssigned;
}
public void setCurrentlyAssigned(boolean isCurrentlyAssigned) {
this.isCurrentlyAssigned = isCurrentlyAssigned;
}
}
Now I want to select those UserCalendar object which has a specific itemId. In my thought if I insert userCalendarId in UserItem and execute
SELECT USERCALENDAR
FROM USER_CALENDAR
WHERE USERCALENDAR.USERCALENDARID IN
(SELECT USERCALENDARID
FROM USERITEM
WHERE USERITEM.ITEMID=ID)
then it might be possible.
Am I right?
How can I insert userCalendarId in UserItem? What is the mapping needed for this?
Thanks and regards.
To have one-to-many you will need column in UserDate that refers to UserCalendar.userCalendarId and column in UserItem to refer to UserDate.userDateId. You will need to specify those columns via many-to-one in those classes.
Then you can use join
SELECT * FROM user_calendar uc
JOIN user_date ud ON ud.user_calendar_id=uc.user_calendar_id
JOIN user_item ui ON ui.user_date_id=ud.user_date_id
WHERE ui.user_item_id=<your value>
Assuming that you have those new columns user_calendar_id and user_date_id in user_date and user_item.
In HQL it will be simpler but I don't remember on top of my head. Check docs.
It could be something like
select ui.userDate.userCaledar from UserItem ui where ui.userItemId=:id
Provided that you added properties userDate and userCalendar via many-to-one