I'm trying to join two tables and fetch all rows from an sql database using a hibernate query. I have two mapping files Offer.hmb.xml and Product.hbm.xml. In my Products class I have this function:
public List<Product> getProducts() {
factory = (new Configuration()).configure().buildSessionFactory();
Session session = factory.getCurrentSession();
session.beginTransaction();
List<Product> products = new ArrayList<Product>();
Product q = new Product();
Query query = session.createQuery("select p from Product p JOIN p.offers o where p.offerID = o.offerID or p.offerID = null");
List<Product> list = query.list();
Iterator<Product> iter = list.iterator();
while (iter.hasNext()) {
Product product = iter.next();
System.out.println(product);
}
Product mapping:
<hibernate-mapping>
<class name="shoppingbasket.Product" table="products">
<id name="productID" type="integer" access="field">
<column name="ProductID" />
<generator class="assigned" />
</id>
<property name="offerID" type="java.lang.Integer" access="field">
<column name="OfferID" />
</property>
<property name="productName" type="java.lang.String" access="field">
<column name="ProductName" length="40" not-null="true"/>
</property>
<property name="unitPrice" type="java.math.BigDecimal" access="field">
<column name="UnitPrice"/>
</property>
<one-to-one name="offers" class="shoppingbasket.Offer" />
</class>
</hibernate-mapping>
Offer mapping:
<hibernate-mapping>
<class name="shoppingbasket.Offer" table="offers">
<id name="offerID" type="integer" access="field">
<column name="OfferID" />
<generator class="assigned" />
</id>
<property name="offerDescription" type="java.lang.String" access="field">
<column name="OfferDescription" length="60" not-null="true"/>
</property>
<property name="shortDescription" type="java.lang.String" access="field">
<column name="ShortDescription" length="10" not-null="false"/>
</property>
<property name="TFTPOTGroup" type="java.lang.Integer" access="field">
<column name="TFTPOTGroup" length="4" not-null="false" default="null"/>
</property>
<property name="discountPercentage" type="java.lang.Double" access="field">
<column name="DiscountPercentage" not-null="false" default="null"/>
</property>
</class>
</hibernate-mapping>
The query runs but only returns the first two rows however if I convert the query to SQL and run it in phpmyadmin it returns all rows. What am I doing wrong? I'm new to Java and HQL any pointers/help would be appreciated
Related
I want to get id and name of user, who have mhId = "AAA" (mhId is a column in table User_MonHoc. In User_MonHoc, mhid + user_id are primary key).
Table User:
<hibernate-mapping>
<class name="entites.User" table="user" catalog="bthibernate" optimistic-lock="version">
<id name="username" type="string">
<column name="username" length="100" />
<generator class="assigned" />
</id>
<property name="password" type="string">
<column name="password" length="100" not-null="true" />
</property>
<property name="note" type="byte">
<column name="note" not-null="true" />
</property>
<property name="name" type="string">
<column name="name" length="100" not-null="true" />
</property>
<set name="userMonhocs" table="user_monhoc" inverse="true" lazy="true" fetch="select">
<key>
<column name="user_id" length="100" not-null="true" />
</key>
<one-to-many class="entites.UserMonhoc" />
</set>
</class>
Table User_MonHoc
<hibernate-mapping>
<class name="entites.UserMonhoc" table="user_monhoc" catalog="bthibernate" optimistic-lock="version">
<composite-id name="id" class="entites.UserMonhocId">
<key-property name="userId" type="string">
<column name="user_id" length="100" />
</key-property>
<key-property name="mhId" type="string">
<column name="mh_id" length="100" />
</key-property>
</composite-id>
<many-to-one name="monhoc" class="entites.Monhoc" update="false" insert="false" fetch="select">
<column name="mh_id" length="100" not-null="true" />
</many-to-one>
<many-to-one name="user" class="entites.User" update="false" insert="false" fetch="select">
<column name="user_id" length="100" not-null="true" />
</many-to-one>
<property name="thoigianDk" type="timestamp">
<column name="thoigian_dk" length="19" not-null="true" />
</property>
</class>
I want to get id and name of user, who have mhId = "AAA" (mhId is a column in table User_MH).
Thank you!
You should join User and User_MH table in a SQL or HQL query. set alias to User_MH in your query o access User_MH table in where clause:
SQL :
SELECT tbl_user.useranme,tbl_user_mh.user_id FROM User AS tbl_user
INNER JOIN User_MH AS tbl_user_mh ON tbl_user.id=tbl_user_mh.user_id
WHERE tbl_user_mh.mhdl = 'AAA
I have two tables: patient_data and patient_diagnosis
Patient_data contains personal data of patient like: pid (pkey), gender, birth_date
patient_diagnosis contains the diagnosis data of the registered patients. It has fields like: record_id (pkey), pid (fkey to patient_data(pid)), diagnosis_date and other related fields.
Now, I want to join these two tables on pid and have all these fields in a single type of object.
Here is the mapping file:
<hibernate-mapping>
<class catalog="emr" name="in.Models.Emr" table="patient_diagnosis">
<id name="recordid" type="long">
<column name="record_id"/>
</id>
<property name="diagnosisDate" type="timestamp">
<column length="19" name="diagnosis_date" not-null="true"/>
</property>
<property name="snomedTermPrimary" type="long">
<column name="snomed_term_primary" not-null="true" />
</property>
<property name="snomedTermSecondary" type="string">
<column name="snomed_term_secondary" />
</property>
<property name="episodeNo" type="long">
<column name="episode_no" not-null="true" />
</property>
<property name="pid" type="long">
<column name="pid" not-null="true" />
</property>
<join table="patient_data">
<key column="pid"/>
<property name="gender" type="string">
<column name="gender" not-null="true"/>
</property>
<property name="birthDate" type="timestamp">
<column length="19" name="birth_date" not-null="true"/>
</property>
</join>
</class>
</hibernate-mapping>
But, the join applies on patient_diagnosis.record_id = patient_data.pid instead of patient_diagnosis.pid = patient_data.pid i.e. HQL applies on primary key of first table with mentioned column from second table.
Please provide the solution so that join can be applied on mentioned column from first with mentioned column from second table. Or is there another way out?
Please note that in case I didn't create classes for patient_data or patient_diagnosis. But, just Emr class having combination of fields of these tables is created.
Try giving foreign key
<id name="pid" type="java.lang.Long">
<column name="pid" />
<generator class="foreign">
<param name="property">patient_data</param>
</generator>
</id>
I am not sure but maybe this should work.
And
<one-to-one name="patient_data" class="in.Models.Emr"
cascade="save-update"></one-to-one>
Similarly in Join class
<one-to-one name="patient_diagnosis" class="in.Models.Emr"
cascade="save-update"></one-to-one>
I hope this helps you.
I have the following Hibernate Mappings:
<class name="Database.Content" table="..." schema="" catalog="...">
<id name="id">
<column name="id" sql-type="int" not-null="true"/>
</id>
<property name="week">
<column name="week" sql-type="int"/>
</property>
<property name="day">
<column name="day" sql-type="int"/>
</property>
<property name="hour">
<column name="hour" sql-type="int"/>
</property>
<property name="type">
<column name="type" sql-type="int" not-null="true"/>
</property>
<many-to-one name="group" class="Database.Group">
<column name="group"/>
</many-to-one>
<many-to-one name="table" class="Database.Table">
<column name="table" not-null="true"/>
</many-to-one>
<list name="entries" inverse="true" table="...">
<key>
<column name="content" not-null="true"/>
</key>
<list-index column="id"/>
<one-to-many not-found="ignore" class="Database.Entry"/>
</list>
</class>
<class name="Database.Entry" table="..." schema="" catalog="...">
<id name="id">
<column name="id" sql-type="int" not-null="true"/>
</id>
<property name="teacher">
<column name="teacher" sql-type="int" not-null="true"/>
</property>
<property name="course">
<column name="course" sql-type="int" not-null="true"/>
</property>
<property name="room">
<column name="room" sql-type="int" not-null="true"/>
</property>
<property name="p">
<column name="p" sql-type="int" not-null="true"/>
</property>
<many-to-one name="content" class="Database.Content" fetch="join" lazy="false">
<column name="content" not-null="true"/>
</many-to-one>
</class>
Now I am trying to query all contents with the corresponding entries:
List<Content> contents = session.createQuery("from Content c WHERE c.day IN :days ").setParameterList("days", days).list();
The query returns the correct response. However, when I do the following:
contents.get(0).getEntries()
there is a bunch of null values. What is the correct way to eager load all corresponding entries for each content?
I have about 20,000 content records, and most of the records have only one entry.
If I set lazy="false" for the list of entries, I get Java heap space error.
I ended up fetching entries and joining contents:
List<Entry> entries = session.createQuery("select e from Entry e Join e.content c WHERE c.day IN :days ").setParameterList("days", days).list();
I also changed lazy to proxy in:
<many-to-one name="content" class="Database.Content" fetch="join" lazy="proxy">
<column name="content" not-null="true"/>
</many-to-one>
Add lazy=false attribute:
<list name="entries" inverse="true" table="up_timetable_entries" lazy="false">
Hope helped you!
Try calling:
contents.get(0).getEntries().size();
To force hibernate to load the children.
Let's say I have this named HQL (findRoomQuery):
select r from House h inner join h.roomList r
where h.address = :address and r.roomNo = :roomNo
The mapping of House entity is like this:
<class name="com.example.House" table="house">
<id name="id" column="id" type="long">
<generator class="assigned" />
</id>
<property name="address" column="address" type="string" length="100" not-null="false"/>
<set name="roomList" cascade="none" lazy="false" fetch="join" inverse="true">
<key>
<column name="house_id"/>
</key>
<one-to-many class="com.example.Room"/>
</set>
</class>
While the Room entity is like this:
<class name="com.example.Room" table="room">
<id name="id" column="id" type="long">
<generator class="assigned" />
</id>
<property name="houseId" column="house_id" type="long" not-null="true"/>
<property name="roomNo" column="room_no" type="string" length="4" not-null="false"/>
</class>
The relationship is a House can has one or many Room.
The code to execute the query is like this:
Query query = getSession().createQuery("findRoomQuery")
.setParameter("address", address)
.setParameter("roomNo", roomNo);
return query.list();
You can see the HQL return Room entities from select r (r is alias of h.roomList).
How to do the same thing with Hibernate Criteria Query?
Is it possible?
Try this one
Criteria criteria = session.createCriteria(House.class, "house");
criteria.createAlias("house.roomList", "roomList");
criteria.add(Restrictions.eq("house.address",address));
criteria.add(Restrictions.eq("roomList.roomNo", roomNo));
criteria.setProjection(Projections.property("roomList"));
Room r = (Room) criteria.uniqueResult();
replace
<property name="houseId" column="house_id" type="long" not-null="true"/>
to
<many-to-one name="houseId" class="com.example.House" fetch="select">
<column name="house_id" not-null="true" />
</many-to-one>
Problem #1:
I have three tables; User, UserRole, and UserRoleRelationships (join table). The UserRole table contain all the user roles which I want to associate with the user. When I insert a new user I want to add a new user and add a new association in the join table. Now, when I'm running the query for inserting a new user:
IWUser iwUser = new IWUser();
iwUser.setUsername("username");
iwUser.setFullName("fullName");
iwUser.setEmail("email");
iwUser.setPassword("password");
iwUser.setPrivatephone("55555");
iwUser.setWorkphone("777");
Set<IWUserRole> roleList = new HashSet<IWUserRole>();
IWUserRole iwUserRole = new IWUserRole();
iwUserRole.setRole("ROLE_USER");
roleList.add(iwUserRole);
iwUser.setUserRole(roleList);
iwUserManagementService.saveOrUpdate(iwUser);
hibernate is running the following queries:
Hibernate: insert into dbo.Users (Username, Password, Email, Workphone, Privatephone, FullName) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into dbo.UserRoles (Role) values (?)
Hibernate: insert into UserRoleRelationships (UserId, RoleId) values (?, ?)
My hibernate mapping looks like:
IWUser.hbm.xml:
<hibernate-mapping>
<class name="domain.IWUser" schema="dbo" table="Users">
<id name="userId" type="int">
<column name="UserId"/>
<generator class="native"/>
</id>
<property name="username" type="string">
<column name="Username" not-null="true"/>
</property>
<property name="password" type="string">
<column name="Password" not-null="true"/>
</property>
<property name="email" type="string">
<column name="Email" not-null="false"/>
</property>
<property name="workphone" type="string">
<column name="Workphone" not-null="false"/>
</property>
<property name="privatephone" type="string">
<column name="Privatephone" not-null="false"/>
</property>
<property name="fullName" type="string">
<column name="FullName" not-null="false"/>
</property>
<set cascade="all" inverse="false" name="userRole" table="UserRoleRelationships" lazy="true" >
<key>
<column name="UserId"/>
</key>
<many-to-many class="domain.IWUserRole" column="RoleId"/>
</set>
</class>
</hibernate-mapping>
IWUserRole.hbm.xml:
<hibernate-mapping>
<class name="domain.IWUserRole" schema="dbo" table="UserRoles">
<id name="roleId" type="int">
<column name="RoleId"/>
<generator class="native"/>
</id>
<property name="role" type="string">
<column name="Role" not-null="true"/>
</property>
<set cascade="all" inverse="false" name="user" table="UserRoleRelationships" lazy="true">
<key>
<column name="RoleId"/>
</key>
<many-to-many class="domain.IWUser" column="UserId"/>
</set>
</class>
</hibernate-mapping>
How can I get hibernate to save the new user with an existing user role in the join table?
Problem #2:
When I update the user, hibernate delete the relations in the join table. How can I avoid this?
How can I get hibernate to save the new user with an existing user role in the join table?
Retrieve the user role entity and put that into the list instead of always creating a new one.
I mean this part:
IWUserRole iwUserRole = new IWUserRole();
iwUserRole.setRole("ROLE_USER");
Instead, you'd issue a query like select r from IWUserRole where r.role = 'ROLE_USER'