Can we persist inner enums on Hibernate? - java

I created an inner enum "UserType" inside my class "User", which is used to determine if an instance of a User is a BASIC, a DEPARTMENT_EXCLUSIVE, or a SUPERUSER. Here's a snippet of the code:
public class User {
private String id, lastName, firstName, middleName, password;
private UserType userType;
public void setId(String id) {
this.id = id;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public void setPassword(String password) {
this.password = Encryption.encrypt(password);
}
public void setUserType(UserType userType) {
this.userType = userType;
}
public String getId() {
return id;
}
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public String getMiddleName() {
return middleName;
}
public String getPassword() {
return password;
}
public UserType getUserType() {
return userType;
}
public enum UserType {
BASIC, DEPARTMENT_HEAD, SUPERUSER;
}
}
Now, I want to save the instantiated object to my MySQL database using an ORM. I'm using Hibernate. Here's my Hibernate mapping file snippet inside the class tag:
<id name="id" type="string" column="id"/>
<property name="lastName" column="lastName" type="string" not-null="true"/>
<property name="firstName" column="firstName" type="string"/>
<property name="middleName" column="middleName" type="string"/>
<property name="password" column="password" type="string" not-null="true"/>
<property name="userType" column="userType" not-null="true">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">com.fileManagement.dataDesign.User.UserType</param>
<param name="type">12</param>
<param name="useNamed">true</param>
</type>
</property>
I ran some tests and an exception was throw, telling that the enum couldn't be found. Here's the test code:
SessionFactory f = HibernateUtil.getSessionFactory();
Session s = f.openSession();
Transaction t = s.beginTransaction();
User user = new User();
user.setId("0090713");
user.setLastName("Nocos");
user.setFirstName("Warren");
user.setMiddleName("Manlangit");
user.setPassword("wang1234");
user.setUserType(UserType.DEPARTMENT_HEAD);
s.save(user);
t.commit();
s.close();
f.close();
And here's the snippet of the exception stack trace :
Caused by: org.hibernate.HibernateException: Enum class not found
at org.hibernate.type.EnumType.setParameterValues(EnumType.java:244)
at org.hibernate.type.TypeFactory.injectParameters(TypeFactory.java:131)
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:214)
... 12 more
Caused by: java.lang.ClassNotFoundException: com.fileManagement.dataDesign.User.UserType
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:340)
at org.hibernate.internal.util.ReflectHelper.classForName(ReflectHelper.java:171)
at org.hibernate.type.EnumType.setParameterValues(EnumType.java:241)
... 14 more
I tried making the enum as an outer one and it worked well, but I really want to place this inside the "User" class as an inner one due to a design choice, since it's only usable on that class. Is it possible to do that way? If yes, how?

As mentioned in my comments, try declaring the enum class in mapping file as:
com.fileManagement.dataDesign.User$UserType
Generally if we want to access any inner classes in Hibernate then we need to use the $ symbol.

Related

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.

org.hibernate.PropertyNotFoundException: Could not find a getter for id in class model.Contact

I am trying to learn Hibernate and I am following this tutorial: http://www.visualcplusdotnet.com/javaopensource/javahibernateswingdesktopapp5.html except I am using my own sample database. I have reverse engineered the POJOs for my contact table which looks like this:
and Netbeans auto-generated a .java file that looked like this (Contact.java):
package model;
// Generated Mar 6, 2015 12:04:10 AM by Hibernate Tools 4.3.1
/**
* Contact generated by hbm2java
*/
public class Contact implements java.io.Serializable {
private Integer id;
private String firstname;
private String lastname;
private String email;
private String phone;
private boolean active;
public Contact() {
}
public Contact(String firstname, String lastname, boolean active) {
this.firstname = firstname;
this.lastname = lastname;
this.active = active;
}
public Contact(String firstname, String lastname, String email, String phone, boolean active) {
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
this.phone = phone;
this.active = active;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstname() {
return this.firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return this.lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return this.phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean isActive() {
return this.active;
}
public void setActive(boolean active) {
this.active = active;
}
}
and a .xml file that looks like this (Contact.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 Mar 6, 2015 12:04:12 AM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="model.Contact" table="contact" catalog="crmtool" optimistic-lock="version">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="firstname" type="string">
<column name="firstname" length="100" not-null="true" />
</property>
<property name="lastname" type="string">
<column name="lastname" length="100" not-null="true" />
</property>
<property name="email" type="string">
<column name="email" length="100" />
</property>
<property name="phone" type="string">
<column name="phone" length="10" />
</property>
<property name="active" type="boolean">
<column name="active" not-null="true" />
</property>
</class>
</hibernate-mapping>
After a clean and build, when I run this HQL Query:
from Contact
I get this error:
org.hibernate.PropertyNotFoundException: Could not find a getter for id in class model.Contact
at org.hibernate.property.BasicPropertyAccessor.createGetter(BasicPropertyAccessor.java:310)
at org.hibernate.property.BasicPropertyAccessor.getGetter(BasicPropertyAccessor.java:304)
at org.hibernate.tuple.PropertyFactory.getGetter(PropertyFactory.java:497)
at org.hibernate.tuple.PropertyFactory.buildIdentifierAttribute(PropertyFactory.java:87)
at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:163)
at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:520)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:148)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:163)
at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:135)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:400)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)
after reading the answers to these questions:
Hibernate - PropertyNotFoundException: Could not find a getter for
PropertyNotFoundException: Could not find a getter for lastMoveDate in class com.hib.objects.GameBoard
org.hibernate.PropertyNotFoundException: could not find getter for customerId in class Address
I figured the answer must be something wrong with the way id is being capitalized by the getter, so I tried:
public Integer getid() {
return this.id;
}
public int getId() {
return this.id;
}
public int getid() {
return this.id;
}
All kinds of things, but still nothing works.
Does anyone know why I'm receiving this error?
Here it is :
Your configuration looks correct. Can do a simple test just rename your id attribute to say contactId and create getters and setters,modify Contact.hbm.xml accordingly and see if hibernate complains of not being able to getter method for the new attribute. Getting this feeling there is some project cleaning up issue
Regards,
Don't try to solve. Change the name of id column to "cid" or "contact_id" or whatever you want.

#AttributeOverrides and #Embeddable not working

This is from Hibernate Recipies book at chapter 3 first question when I am trying to run I am getting the following error Exception in thread "main" org.hibernate.MappingException: Repeated column in mapping for entity: com.fun.hibernate.auto.idgen.Order column: address (should be mapped with insert="false" update="false")
Here is the code
#Entity
#org.hibernate.annotations.Entity(dynamicInsert=true, dynamicUpdate=true)
#Table(name="ORDERS")
public class Order {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE,generator="orderSequence" )
#SequenceGenerator(name="orderSequence",sequenceName="ORDERSEQ")
private Long id;
private Contact weekdayContact;
private Contact holidayContact;
public Order() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Contact getWeekdayContact() {
return weekdayContact;
}
public void setWeekdayContact(Contact weekdayContact) {
this.weekdayContact = weekdayContact;
}
#Embedded
#AttributeOverrides({
#AttributeOverride(name="recipient",column=#Column(name ="HOLIDAY_RECIPIENT")),
#AttributeOverride(name="phone",column=#Column(name ="HOLIDAY_PHONE")),
#AttributeOverride(name="address",column=#Column(name ="HOLIDAY_ADDRESS"))
})
public Contact getHolidayContact() {
return holidayContact;
}
public void setHolidayContact(Contact holidayContact) {
this.holidayContact = holidayContact;
}
}
Embeddable Object
#Embeddable
public class Contact {
private String recipient;
private String phone;
private String address;
public Contact() {
}
#Column(name = "WEEKDAY_RECIPIENT")
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
#Column(name ="WEEKDAY_PHONE")
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
#Column(name ="WEEKDAY_ADDRESS")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Any ideas how to solve this??????????????
Reading the Hibernate Recipes book cited above I could easily reach the exactly point you described on your question.
I couldn't create the same environment that you are working on, so I had to read and interpret what the book says about mapping by annotations and by external configuration files (XML).
By studying your code and the book chapter I think that there are a high probably that you doing some redundancy in the mapping your embedded object, so there is what I think it's the exactly(or close to it) problem:
In the configuration file the book says to create the manual mapping by tags, just like this:
<component name="weekdayContact" class="Contact">
<property name="recipient" type="string" column="WEEKDAY_RECIPIENT" />
<property name="phone" type="string" column="WEEKDAY_PHONE" />
<property name="address" type="string" column="WEEKDAY_ADDRESS" />
</component>
<component name="holidayContact" class="Contact">
<property name="recipient" type="string" column="HOLIDAY_RECIPIENT" />
<property name="phone" type="string" column="HOLIDAY_PHONE" />
<property name="address" type="string" column="HOLIDAY_ADDRESS" />
</component>
Just above this the book also says that you need to create the mapping by annotations:
#Embedded
#AttributeOverrides({
#AttributeOverride(name="recipient",column=#Column(name ="HOLIDAY_RECIPIENT")),
#AttributeOverride(name="phone",column=#Column(name ="HOLIDAY_PHONE")),
#AttributeOverride(name="address",column=#Column(name ="HOLIDAY_ADDRESS"))
})
public Contact getHolidayContact() {
return holidayContact;
}
So, I think that's there only two possible things happening here:
You are mapping the embedded object in the XML file and in the class. In this case you should do it just by one type, preferably by annotations.
I could see that your code differs that the one the book states, and this may be causing the failure. In this case you should read again your whole code and see if there's any differential than the book one, and then correct it to be working just like it's written in the examples.
That's it, good luck!

MYSQL SQL syntax error while i use hibernate

I am using hibernate as a persistence layer, here is the sample of my code, but here my hql queries:
Query q = s.createQuery("from Login where name=:user and passw =:passw");
q.setParameter("user",username);
q.setParameter("passw", passw);
Query q = s.createSQLQuery("SELECT * from Good where Good.supplier =:supl AND Good.name =:gname AND Good.dates >=:sdate and Good.dates <=:fdate").addEntity(Good.class);
q.setParameter("supl",sup);
q.setParameter("gname", gname);
q.setParameter("sdate", sdate);
q.setParameter("fdate",fdate);
sdate and fdate parametrs are string, are they ok in this case? it throws this exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.login login0_ where login0_.name='Tom'' at line 1
Login.hbm.xml
<hibernate-mapping>
<class name="kz.bimash.FoodSec.model.Login" table="login" catalog="foodsec">
<id name="id" type="java.lang.Integer">
<column name="Id" />
<generator class="increment" />
</id>
<property name="name" type="string">
<column name="name" length="50" not-null="true" unique="true" />
</property>
<property name="passw" type="string">
<column name="passw" length="50" not-null="true" />
</property>
<property name="type" type="string">
<column name="type" length="45" not-null="true" />
</property>
<property name="userId" type="int">
<column name="userId" not-null="true" />
</property>
</class>
Login pojo class
public class Login implements java.io.Serializable {
private Integer id;
private String name;
private String passw;
private String type;
private int userId;
public Login() {
}
public Login(String username, String password, String type, int userId) {
this.name = username;
this.passw = password;
this.type = type;
this.userId = userId;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String username) {
this.name = username;
}
public String getPassw() {
return this.passw;
}
public void setPassw(String password) {
this.passw = password;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public int getUserId() {
return this.userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}
Login DAO class
#Repository
public class LoginDAO {
#Autowired
private SessionFactory sf;
#SuppressWarnings("empty-statement")
public String[] Authorise(String username, String passw){
Session s = sf.getCurrentSession();
s.beginTransaction();
Query q = s.createQuery("from Login where name=:user and passw =:passw");
q.setParameter("user",username);
q.setParameter("passw", passw);
q.setMaxResults(1);
String[] str = null;
Login login = null;
for(Iterator it = q.iterate(); it.hasNext();){
login = (Login)it.next();
}
if(login != null){
str = new String[]{login.getType(), String.valueOf(login.getUserId())};
}
s.getTransaction().commit();
return str;
}
public boolean checkLogin(String username){
Session s = sf.getCurrentSession();
s.beginTransaction();
// String s_sql ="SELECT * FROM Login WHERE NAME="+username;
Query q = s.createQuery("from Login where name = :usern");
q.setParameter("usern", username);
// Query q=s.createSQLQuery(s_sql);
List<Login> logins =null;
logins= (List<Login>)q.list();
s.getTransaction().commit();
if(logins !=null)
return true;
else
return false;
}
}
There's a problem with the following segment of the code:
Query q = s.createSQLQuery("SELECT * from Good where Good.supplier =:supl AND Good.name =:gname AND Good.dates >=:sdate and Good.dates <=:fdate").addEntity(Good.class);
You are writing an SQL & not an HQL. That is why you have used session.createSQLQuery(...) and not session.createQuery(...). createSQLQuery(...) always returns a reference of org.hibernate.SQLQuery, while you have assigned it to a variable of Query.
I'm surprised why didn't you get a Compile-time error.
Try to assign it to a SQLQuery variable & check whether it's working or not.

JPA - using annotations in a model

My application runs on JPA/Hibernate, Spring and Wicket. I'm trying to convert our ORM from XML files to JPA annotations. The annotated model looks like this:
#Entity
#Table(name = "APP_USER")
public class User extends BaseObject {
private Long id;
private String firstName;
private String lastName;
private String email;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name="FIRST_NAME")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name="LAST_NAME")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name="EMAIL")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
/**
* #return Returns firstName and lastName
*/
public String getFullName() {
return firstName + ' ' + lastName;
}
}
Originally, though, it was without annotation and the mapping was described in User.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.appfuse.model.User" table="app_user">
<id name="id" column="id" unsaved-value="null">
<generator class="increment"/>
</id>
<property name="firstName" column="first_name" not-null="true"/>
<property name="lastName" column="last_name" not-null="true"/>
<property name="email" column="email"/>
</class>
</hibernate-mapping>
When I delete the mapping file and try to use just the annotations, the entityManagerFactory doesn't get created, with the exception
org.hibernate.PropertyNotFoundException:
Could not find a setter for property
fullName in class
org.appfuse.model.User.
There's no mapping set for this property, because it's just a convenience method. What do I do wrong?
Mark the method as #Transient so Hibernate will ignore it:
/**
* #return Returns firstName and lastName
*/
#Transient
public String getFullName() {
return firstName + ' ' + lastName;
}
By default, everything that looks like a getter is mapped.

Categories

Resources