Separate entity for primary keys - java

I have two tables as below.
"User Acc" is user's profile details and user's login details(username password) are in a seperate table called login.When I generated the entities in Netbeans IDE, there were 2 tables for login(database) table. One generated entity is "Login", another one is "LoginId".Login entity has a reference to LoginId and UserAcc entity. LoginId entity has username and password which were in login database table.UserAcc has primary key which is INT for each user.That key is the foreign key of login table.
Now I want to check the user # loging. How I do is, I create a LoginId instance and set the user name and password and then check any object which has same LoginId. Here is the code.
uName and pw are strings and taken from user input.
LoginId id=new LoginId(uName, pw);
Session ses = NewHibernateUtil.getSessionFactory().openSession();
Criteria crit = ses.createCriteria(Login.class);
crit.add(Restrictions.eq("id", id));
Entities.Login log = (Entities.Login)crit.uniqueResult();
But eventhough there are existing usernames and passwords matching with given username and password, the log is always null.
Any one tell me where I should check and what the problem is. Thank you.
And my other problem is why a separate entity("LoginId") is created for two columns(primary keys) in one database table and another entity for that its database table .
for login;
<hibernate-mapping>
<class name="Entities.Login" table="login" catalog="pcw">
<composite-id name="id" class="Entities.LoginId">
<key-property name="uname" type="string">
<column name="uname" length="10" />
</key-property>
<key-property name="pw" type="string">
<column name="pw" length="10" />
</key-property>
</composite-id>
<many-to-one name="useracc" class="Entities.Useracc" fetch="select">
<column name="UserAcc_uid" not-null="true" />
</many-to-one>
</class>
for UserAcc:
<hibernate-mapping>
<class name="Entities.Useracc" table="useracc" catalog="pcw">
<id name="uid" type="java.lang.Integer">
<column name="uid" />
<generator class="identity" />
</id>
<property name="fname" type="string">
<column name="fname" length="45" />
</property>
<property name="sname" type="string">
<column name="sname" length="45" />
</property>
<property name="RDate" type="date">
<column name="r_date" length="10" />
</property>
<property name="street" type="string">
<column name="street" length="45" />
</property>
<property name="city" type="string">
<column name="city" length="45" />
</property>
<property name="email" type="string">
<column name="email" length="45" />
</property>
<property name="tel" type="string">
<column name="tel" length="45" />
</property>
<set name="comments" inverse="true" cascade="all">
<key>
<column name="UserAcc_uid" not-null="true" />
</key>
<one-to-many class="Entities.Comment" />
</set>
<set name="logins" inverse="true" cascade="all">
<key>
<column name="UserAcc_uid" not-null="true" />
</key>
<one-to-many class="Entities.Login" />
</set>
</class>

Anyway you can use HQL to solve it it will look more and less like this:
public boolean authenticate(Sting username,String pass){
Session ses = NewHibernateUtil.getSessionFactory().openSession();
String sql = "from Login login where login.username:= username and login.pass = :=pass";
Query query = session.createQuery(sql);
query.setString("username",username);
query.setString("pass",pass);
List<Login> result = query.list();
//close session, transaction,etc....
if (result ==null)
return false;
else
return true;
}

Related

Hibernate select all query executes extremely slowly

I have some simple code that is supposed to select all teacher objects from a table of teachers in my mysql database. When I run similar queries for other domain objects, it is extremely fast, but for some reason this query takes forever. Also if I run a select all query from mysql workbench it executes instantly, so I think the problem is with my hibernate mapping. There are only 30 ish entries in the table so there is no reason this should be taking long.
Hibernate mapping xml file:
<hibernate-mapping>
<class name="org.myschool.domain.Teacher" table="teacher">
<id name="teacher_id" type="java.lang.Integer">
<column name="teacher_id" />
<generator class="increment" />
</id>
<property name="firstName" type="java.lang.String">
<column name="first_name" length="20" not-null="true"/>
</property>
<property name="lastName" type="java.lang.String">
<column name="last_name" length="30" not-null="true" />
</property>
<property name="middleInitial" type="java.lang.String">
<column name="middle_initial" length="1" not-null = "false"/>
</property>
<set name="wantsCourses" table="teacher_want" inverse="false" lazy="true" fetch="select" cascade="all">
<key>
<column name="teacher_id" not-null="true" />
</key>
<many-to-many entity-name="org.myschool.domain.Course">
<column name="course_id" not-null="true" />
</many-to-many>
</set>
<set name="eligibleCourses" table="teacher_eligible" inverse="false" lazy="true" fetch="select" cascade="all">
<key>
<column name="teacher_id" not-null="true" />
</key>
<many-to-many entity-name="org.myschool.domain.Course">
<column name="course_id" not-null="true" />
</many-to-many>
</set>
<set name="teacherTranscript" table="assigned_course" inverse="true" lazy="true" fetch="select">
<key>
<column name="teacher_id" not-null="true" />
</key>
<one-to-many class="org.myschool.domain.AssignedCourse" />
</set>
</class>
</hibernate-mapping>
This is the method being called that takes so long :
public List<Teacher> findAll() {
try {
#SuppressWarnings("unchecked")
List<Teacher> results = (List<Teacher>) sessionFactory.getCurrentSession()
.createCriteria("org.myschool.domain.Teacher").list();
log.debug("find all successful, result size: " + results.size());
return results;
} catch (RuntimeException re) {
log.error("find all failed", re);
throw re;
}
}
And this is the actual hibernate query being executed:
Hibernate: select this_.teacher_id as teacher_1_8_0_, this_.first_name as first_na2_8_0_, this_.last_name as last_nam3_8_0_, this_.middle_initial as middle_i4_8_0_ from teacher this_
Here's the sql command that makes the teacher table:
CREATE TABLE teacher(
teacher_id INT(6) UNSIGNED NOT NULL PRIMARY KEY,
first_name VARCHAR(20) NOT NULL,
middle_initial CHAR(1),
last_name VARCHAR(30) NOT NULL)
Thanks for your help!

Hibernate TransientPropertyValueException When saving data

I am trying to insert data to the DB using hibernate . Here is how I going perform that action
session.beginTransaction();
pojo.StuDetails stu = new StuDetails();
stu.setFName(f_name);
stu.setLName(l_name);
stu.setSex(sex);
stu.setDob(dob);
pojo.Subject sub = new Subject(subject, day, time);
pojo.SubjectHasStuDetails shs = new SubjectHasStuDetails(stu, sub);
session.save(shs);
session.getTransaction().commit();
But It gives me an error saying
Exception in thread "main"
org.hibernate.TransientPropertyValueException: Not-null property
references a transient value - transient instance must be saved before
current operation
Here is my student details entity
public class StuDetails implements java.io.Serializable {
private Integer id;
private String FName;
private String LName;
private String sex;
private String dob;
private Set subjectHasStuDetailses = new HashSet();
...
//constructors and getters, setters
My StudentDetails hbm.xml
<hibernate-mapping>
<class name="pojo.StuDetails" table="stu_details" catalog="laravel_test" optimistic-lock="version">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="FName" type="string">
<column name="f_name" length="45" not-null="true" />
</property>
<property name="LName" type="string">
<column name="l_name" length="45" not-null="true" />
</property>
<property name="sex" type="string">
<column name="sex" length="45" not-null="true" />
</property>
<property name="dob" type="string">
<column name="dob" length="45" not-null="true" />
</property>
<set name="subjectHasStuDetailses" table="subject_has_stu_details" inverse="true" lazy="true" fetch="select">
<key>
<column name="stu_details_id" not-null="true" />
</key>
<one-to-many class="pojo.SubjectHasStuDetails" />
</set>
</class>
</hibernate-mapping>
My Subject Entity looks like
public class Subject implements java.io.Serializable {
private Integer id;
private String subName;
private String day;
private String time;
private Set subjectHasStuDetailses = new HashSet();
...
//constructors and getters, setters
Subject.hbm.xml
<hibernate-mapping>
<class name="pojo.Subject" table="subject" catalog="laravel_test" optimistic-lock="version">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="subName" type="string">
<column name="sub_name" length="45" not-null="true" />
</property>
<property name="day" type="string">
<column name="day" length="45" not-null="true" />
</property>
<property name="time" type="string">
<column name="time" length="45" not-null="true" />
</property>
<set name="subjectHasStuDetailses" table="subject_has_stu_details" inverse="true" lazy="true" fetch="select">
<key>
<column name="subject_id" not-null="true" />
</key>
<one-to-many class="pojo.SubjectHasStuDetails" />
</set>
</class>
</hibernate-mapping>
Here is the SubjetcHasStuDetails Entity
public class SubjectHasStuDetails implements java.io.Serializable {
private Integer id;
private StuDetails stuDetails;
private Subject subject;
...
//constructors and getters, setters
SubjectHasStuDetials.hbm.xml
<hibernate-mapping>
<class name="pojo.SubjectHasStuDetails" table="subject_has_stu_details"
catalog="laravel_test" optimistic-lock="version">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<many-to-one name="stuDetails" class="pojo.StuDetails" fetch="select">
<column name="stu_details_id" not-null="true" />
</many-to-one>
<many-to-one name="subject" class="pojo.Subject" fetch="select" >
<column name="subject_id" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
Can someone help me on this error please ... Thanks..
In your SubjectHasStuDetials.hbm.xml make these changes :
<many-to-one name="stuDetails" class="pojo.StuDetails" fetch="select" cascade="all">
<column name="stu_details_id" not-null="true" />
</many-to-one>
<many-to-one name="subject" class="pojo.Subject" fetch="select" cascade="all" >
<column name="subject_id" not-null="true" />
</many-to-one>
Add cascade="all" attribute to both stuDetails and subject many-to-one tags.
Cascade attribute is mandatory, when ever we apply relationship
between objects, cascade attribute transfers operations done on one
object onto its related child objects
If we write cascade = “all” then changes at parent class object will
be effected to child class object too, if we write cascade = “all”
then all operations like insert, delete, update at parent object will
be effected to child object also.
Example: if we apply insert(or update or delete) operation on parent
class object, then child class objects will also be stored into the
database.

Hibernate order-by removing rows

I have a one-to-Many Set defined in my mapping file, and when I use the order-by property the data in the Set will be missing rows depending on what property I use to order.
<hibernate-mapping>
<class name="domain.StudentUser" table="student_user" >
....
<set name="studentCourseses" inverse="true" order-by="import_date ASC">
<key>
<column name="student_userid" length="15" not-null="true" />
</key>
<one-to-many class="domain.StudentCourses" />
</set>
</hibernate-mapping>
public StudentUser findById(java.lang.String id) {
log.debug("getting StudentUser instance with id: " + id);
try {
StudentUser instance = (StudentUser) getSession().get(
"domain.StudentUser", id);
return instance;
} catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}
}
Here i use import_date, but this table has about 15 properties and certain properties will cause rows to be missing from the Set while others don't. It doesn't seem to be data-type specific as I have the issue with a String property but then another String property will work fine and all data will be there. It is always the same rows that are missing no matter the sorting property used, so its not random rows.
The majority of the student_user have data missing, but not all. The rows that end up missing have nothing abnormal about them, meaning no NULL's or anything like that.
As of this point, i just removed the order-by attribute so I can get my app working property, but I still need to know why these issues are happening. So far I have not noticed this behavior in any of the other Set's that i use the order-by attribute with, just this one.
I am using Hibernate 3.5.3 and in case it's helpful, here is the mapping file for the StudentCourses table
<hibernate-mapping>
<class name="domain.StudentCourses" table="student_courses" >
<id name="id" type="integer">
<column name="id" />
<generator class="native" />
</id>
<many-to-one name="classLevel" class="domain.ClassLevel" fetch="select">
<column name="class_level_code" length="2" not-null="true" />
</many-to-one>
<many-to-one name="academicTerm" class="domain.AcademicTerm" fetch="select">
<column name="academic_term_id" not-null="true" />
</many-to-one>
<many-to-one name="studentUser" class="domain.StudentUser" fetch="select">
<column name="student_userid" length="15" not-null="true" />
</many-to-one>
<property name="academicYear" type="integer">
<column name="academic_year" not-null="true" />
</property>
<property name="term" type="string">
<column name="term" length="8" not-null="true" />
</property>
<property name="title" type="string">
<column name="title" length="64" not-null="true" />
</property>
<property name="prefix" type="string">
<column name="prefix" length="8" not-null="true" />
</property>
<property name="courseNum" type="string">
<column name="course_num" length="8" not-null="true" />
</property>
<property name="suffix" type="string">
<column name="suffix" length="8" />
</property>
<property name="sectionNum" type="string">
<column name="section_num" length="8" />
</property>
<property name="units" type="double">
<column name="units" precision="4" not-null="true" unique="true" />
</property>
<property name="letterGrade" type="string">
<column name="letter_grade" length="6" not-null="true" />
</property>
<property name="qtrGpa" type="double">
<column name="qtr_gpa" precision="4" scale="3" not-null="true" />
</property>
<property name="cumGpa" type="double">
<column name="cum_gpa" precision="4" scale="3" not-null="true" />
</property>
<property name="importDate" type="timestamp">
<column name="import_date" length="19" />
</property>
<property name="sourceFileName" type="string">
<column name="source_file_name" length="128" />
</property>
<property name="timeStamp" type="timestamp">
<column name="time_stamp" length="19" not-null="true">
<comment>on update CURRENT_TIMESTAMP</comment>
</column>
</property>
</class>
Update (More Info):
If i directly query the StudentCourses table (CORRECT) vs getting the StudentCourses data from the StudentUser mapping set (INCORRECT) gives me different results, they should match
for(StudentCourses course : getStudentService().retrieveStudentByID("861043440").getStudentCourseses()) { //MISSING DATA
System.out.println(course +" - "+course.getTerm());
}
for(StudentCourses course : (List<StudentCourses>)getStudentService().getStudentCoursesDAO().findByProperty("studentUser.studentUserid", "861043440")) { //ALL DATA CORRECT
System.out.println(course +" - "+course.getTerm());
}
Turns out it had nothing to do with sorting, as adjusting the sorting only fixed the issue for some but not all. The problem was that I had overriden the hashCode method of the StudentCourses object and it was causing collisions when the Set was being populated from the StudentUser object. I fixed this and everything is good now.

HQL equivalent query to criteria query in hibernate many to many relationship?

I have two tables stock and category having many-to-many relationship each other.
Stock.hbm.xml
<hibernate-mapping>
<class name="hibernate.mapping.manytomany.Stock" table="stock">
<id name="stockId" type="java.lang.Integer">
<column name="STOCK_ID" />
<generator class="identity" />
</id>
<property name="stockCode" type="string">
<column name="STOCK_CODE" length="10" not-null="true" unique="true" />
</property>
<property name="stockName" type="string">
<column name="STOCK_NAME" length="20" not-null="true" unique="true" />
</property>
<set name="categories" table="stock_category"
inverse="false" lazy="true" fetch="select" cascade="all" >
<key>
<column name="STOCK_ID" not-null="true" />
</key>
<many-to-many entity-name="hibernate.mapping.manytomany.Category">
<column name="CATEGORY_ID" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
Category.hbm.xml
<hibernate-mapping>
<class name="hibernate.mapping.manytomany.Category" table="category">
<id name="categoryId" type="java.lang.Integer">
<column name="CATEGORY_ID" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="NAME" length="10" not-null="true" />
</property>
<property name="desc" type="string">
<column name="[DESC]" not-null="true" />
</property>
<set name="stocks" table="stock_category" inverse="true" lazy="true"
fetch="select">
<key>
<column name="CATEGORY_ID" not-null="true" />
</key>
<many-to-many entity-name="hibernate.mapping.manytomany.Stock">
<column name="STOCK_ID" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
And this is my criteria query,
Criteria c = session.createCriteria(Category.class, "c");
c.createAlias("c.stocks", "s");
c.add(Restrictions.eq("c.categoryId", 1));
c.setProjection(Projections.projectionList()
.add(Projections.property("s.stockId"))
.add(Projections.property("s.stockName")));
I need equivalent HQL for this scenario..I've tried this but it gives different result,
String query = "select c.stocks.stockId, c.stocks.stockName from Category c where
c.categoryId=1"
Let me know if you need more details.
OK, so apparently, you missed the section about joins in the documentation:
select s.stockId, // equivalent to the s.stockId projection
s.stockName // equivalent to the s.stockName projection
from Category c // equivalent to the root criteria creation
join c.stocks s // equivalent to the alias creation
where c.categoryId = 1 // equivalent to the restriction addition
I am planning to investigate this issue thoroughly. What i doubt from previous answer for now is there should be ON Clause in join statement. Pardon me if my expectation is wrong.
select s.stockId,s.stockName from Category c join c.stocks s
on c.stockId=s.stockId where c.categoryId = 1 ;
//it might be on c.CATEGORY_ID=s.CATEGORY_ID also

one to many relation with column other than Id (Primary Key)

I am trying to map two tables using hibernate one-to-many mapping. But, always it is mapping with the wrong column. Please any body help me on this.
Level4_Master [level_id (PK/Auto Increament), company_id, level_name, next_level_id, ts]
Level3_Master [level_id (PK/Auto Increament), prv_level_id, level_name, next_level_id, ts]
Above are the two tables I am using for the mapping. Here, I wanted to map column next_level_id of Level4_Master with column prv_level_id of Level3_Master. But, hibernate always mapping the column prv_level_id with level_id of Level4_Master as FK. My mapping files are:
<hibernate-mapping>
<class name="com.pojo.Level4" table="Level4_Master">
<id name="levelId" type="java.lang.Integer">
<column name="level_id" />
<generator class="increment" />
</id>
<property name="companyId" >
<column name="company_id" length="10" not-null="true" unique="true" />
</property>
<property name="levelName">
<column name="level_name" length="20" not-null="true" unique="true" />
</property>
<property name="nextLevelId" type="java.lang.Integer">
<column name="next_level_id" />
</property>
<set name="levelList" table="Level3_Master" inverse="true" lazy="true" fetch="select">
<key>
<column name="prv_level_id" not-null="true" />
</key>
<one-to-many class="com.pojo.Level3" />
</set>
</class>
</hibernate-mapping>
and
<hibernate-mapping>
<class name="com.pojo.Level3" table="Level3_Master">
<id name="levelId" type="java.lang.Integer">
<column name="level_id" />
<generator class="increment" />
</id>
<property name="prvLevelId" >
<column name="prv_level_id" length="10" not-null="true" unique="true" />
</property>
<property name="levelName">
<column name="level_name" length="20" not-null="true" unique="true" />
</property>
<property name="nextLevelId" type="java.lang.Integer">
<column name="next_level_id" />
</property>
<set name="levelList" table="Level2_Master" inverse="true" lazy="true" fetch="select">
<key>
<column name="prv_level_id" not-null="true" />
</key>
<one-to-many class="com.pojo.Level2" />
</set>
</class>
</hibernate-mapping>
and my pojo classes are like
class Level4{
private int levelId;
private int companyId;
private String levelName;
private int nextLevelId;
private Set<Level3> levelList = new HashSet<Level3>(0);
private Timestamp ts;
//getter n setter
}
class Level3{
private int levelId;
private int prvLevelId;
private String levelName;
private int nextLevelId;
private Set<Level2> levelList = new HashSet<Level2>(0);
private Timestamp ts;
//getter n setter
}
You need to use property-ref attribute with the property name. The property must add unique="true" in the property mapping.
Example -
<hibernate-mapping><class name="com.pojo.Level4" table="Level4_Master">
<id name="levelId" type="java.lang.Integer">
<column name="level_id" />
<generator class="increment" />
</id>
<property name="companyId" >
<column name="company_id" length="10" not-null="true" unique="true" />
</property>
<property name="levelName">
<column name="level_name" length="20" not-null="true" unique="true" />
</property>
<property name="nextLevelId" type="java.lang.Integer" unique="true">
<column name="next_level_id" />
</property>
<set name="levelList" table="Level3_Master" inverse="true" lazy="true" fetch="select">
<key>
<column name="prv_level_id" not-null="true" property-ref="nextLevelId"/>
</key>
<one-to-many class="com.pojo.Level3" />
</set>

Categories