Hibernate - load children - java

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.

Related

How to select multi tables with WHERE clause

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

Hibernate many-to-one

I have to tables Usuario_tbl and RolUsuario_tbl. I generate java model with hibernate reverse engineering having this .hbm.xml
<hibernate-mapping>
<class name="co.ejemplo.modelo.UsuarioTbl" table="usuario_tbl" catalog="structse_db">
<id name="idUsuario" type="java.lang.Integer">
<column name="id_usuario" />
<generator class="identity" />
</id>
<property name="login" type="string">
<column name="login" length="50" not-null="true" unique="true" />
</property>
<property name="clave" type="string">
<column name="clave" not-null="true" />
</property>
<property name="habilitado" type="byte">
<column name="habilitado" not-null="true" />
</property>
<property name="fechaAlta" type="timestamp">
<column name="fecha_alta" length="19" />
</property>
<property name="fechaBaja" type="timestamp">
<column name="fecha_baja" length="19" />
</property>
<set name="rolUsuarioTbls" table="rol_usuario_tbl" inverse="true" lazy="true" fetch="select">
<key>
<column name="login" not-null="true" />
</key>
<one-to-many class="co.ejemplo.modelo.RolUsuarioTbl" />
</set>
</class>
</hibernate-mapping>
and
<hibernate-mapping>
<class name="co.ejemplo.modelo.RolUsuarioTbl" table="rol_usuario_tbl" catalog="structse_db">
<id name="idUsuarioRol" type="java.lang.Integer">
<column name="id_usuario_rol" />
<generator class="identity" />
</id>
<many-to-one name="usuarioTbl" class="co.ejemplo.modelo.UsuarioTbl" fetch="select">
<column name="login" not-null="true" />
</many-to-one>
<property name="rol" type="string">
<column name="rol" length="50" not-null="true" />
</property>
</class>
</hibernate-mapping>
When I try to save one RolUsuarioTbl using getHibernateTemplate().save(rolUsuarioTbl) hibernate tells me that needs all the UsuarioTbl properties but I only has setting the login in UsuarioTbl.
How can I save RolUsuarioTbl having only login property in UsuarioTbl?
Many to one relations must be by the code of both tables, otherwise hibernate will not recognize the children of the parent table.

Hibernate org.hibernate.MappingException... an associon ..to unmapped class- Many toMany

I have auto generated the code using netbeans to create a Hibernate configuration; so I have two tables mapped like this (Many-to-Many) :
<hibernate-mapping auto-import="true">
<class name="com.antoiovi.jobprograms.entity.Roles" table="roles" catalog="jobprograms">
<id name="rolesName" type="string">
<column name="roles_name" length="20" />
<generator class="assigned" />
</id>
<set name="userses" table="users_roles" inverse="true" lazy="false" fetch="select" cascade="all">
<key>
<column name="role_name" length="20" not-null="true" />
</key>
<many-to-many entity-name="com.antoiovi.jobprograms.entity.Users">
<column name="user_name" length="15" not-null="true" />
</many-to-many>
</set>
</class>
<hibernate-mapping auto-import="true">
<class name="com.antoiovi.jobprograms.entity.Users" table="users" catalog="jobprograms">
<id name="idusers" type="java.lang.Integer">
<column name="idusers" />
<generator class="identity" />
</id>
<property name="userName" type="string">
<column name="user_name" length="15" not-null="true" unique="true" />
</property>
<property name="userPass" type="string">
<column name="user_pass" length="15" not-null="true" />
</property>
<property name="firstName" type="string">
<column name="first_name" length="20" />
</property>
<property name="lastName" type="string">
<column name="last_name" length="25" />
</property>
<set name="roleses" table="users_roles" inverse="true" lazy="false" fetch="select" cascade="all">
<key>
<column name="user_name" length="15" not-null="true" />
</key>
<many-to-many entity-name="com.antoiovi.jobprograms.entity.Roles">
<column name="role_name" length="20" not-null="true" />
</many-to-many>
</set>
<set name="jobprograms" table="jobprogram" inverse="true" lazy="false" fetch="select" cascade="all">
<key>
<column name="users_idusers" not-null="true" />
</key>
<one-to-many class="com.antoiovi.jobprograms.entity.Jobprogram" />
</set>
</class>
I have made some modification as you can see above (auto-import=true, lazy=false), cause i have the error message
rg.hibernate.MappingException: An association from the table users_roles refers to an unmapped class: com.antoiovi.jobprograms.entity.Roles
at org.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:1824)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1756)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1423)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1856)
The config file is
<hibernate-configuration>
org.hibernate.dialect.MySQLDialect
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/jobprograms?zeroDateTimeBehavior=convertToNull
jobprograms_ad
xxxxx
thread
true
org.hibernate.hql.classic.ClassicQueryTranslatorFactory
true
the classes have refernce like this :
'#ManyToMany(fetch=FetchType.LAZY, mappedBy="roleses")
public Set<Users> getUserses() {
return this.userses;
} '
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name="users_roles", catalog="jobprograms", joinColumns = {
#JoinColumn(name="user_name", nullable=false, updatable=false) }, inverseJoinColumns = {
#JoinColumn(name="role_name", nullable=false, updatable=false) })
public Set<Roles> getRoleses() {
return this.roleses;
}
wHEN RUNNING I HAVE THE ERROR org.hibernate.exception.SQLGrammarException, and in fact the entiti is loaded, but the set<> not..,
When testing the error is
org.hibernate.MappingException: An association from the table users_roles refers to an unmapped class: com.antoiovi.jobprograms.entity.Roles, and the HSQL ar not executed.
I tried to look in others post but i couldn't find an answer. Can anybody help me?
In config file the entities are all declared;
I think yhe promlem is in the mapping :
e <set name="roleses" table="users_roles" inverse="false" lazy="true" fetch="select" >
<key >
<column name="user_name" length="15" not-null="true" />
</key>
<many-to-many entity-name="test.Roles" property-ref="rolesName">
<column name="role_name" length="20" not-null="true" />
</many-to-many>
</set>
<set name="jobprograms" table="jobprogram" inverse="true" lazy="true" fetch="select">
<key>
<column name="users_idusers" not-null="true" />
</key>
<one-to-many class="test.Jobprogram" />
</set>
and
enter <class name="test.Roles" table="roles" catalog="jobprograms">
<id name="rolesName" type="string">
<column name="roles_name" length="20" />
<generator class="assigned" />
</id>
<set name="userses" table="users_roles" inverse="true" lazy="true" fetch="select">
<key property-ref="rolesName">
<column name="role_name" length="20" not-null="true" />
</key>
<many-to-many entity-name="test.Users" property-ref="userName">
<column name="user_name" length="15" not-null="true" />
</many-to-many>
</set>
</class>
....
this error
org.hibernate.MappingException: An association from the table users_roles refers to an unmapped class: com.antoiovi.jobprograms.entity.Roles
comes when hibernate configuration dont know about entity(Roles) mapping , either you have missed introducing enitity Roles to the hibernate configuration or you have not used correct name , please check configuraiton file and included com.antoiovi.jobprograms.entity.Roles as resourse
I think to have resolved the problem. Actually the proble are unmapped entities. But this happens because the database is not 'well formed'. Indeed the database ha 3 table users, users_roles, roles; the table roles has only one column as primarykey (varchar),and the table user_roles refers to it from its column user_roles; when forword enginering the ide (in the case netbeans) creates only 2 entities: 'Users', and 'Roles'; So i have re-designed the schema putting some virtual primary key, and creating unique constaint instead. Now i have 3 entities : Users,UserRoles, and Roles.

org.hibernate.exception.MappingException or ConstraintViolation

I am using hibernate 4.1.9. I have Users, and the Users have a list of Accounts, and Accounts have list of Transactions. Here is my hbm.xml
<?xml version="1.0"?>
<class name="User" table="users">
<id name="userId" column="userid">
<generator class="increment"/>
</id>
<property name="username" column="username" not-null="true"/>
<property name="password" column="password" not-null="true"/>
<property name="registerDate" type="timestamp" column="register_date"/>
<list name="accounts" table="accounts" inverse="true" cascade="all">
<key column="userid" not-null="true"/>
<index column="accountid"/>
<one-to-many class="com.joe.data.Account"/>
</list>
</class>
<class name="Account" table="accounts">
<id name="accountId" column="accountid">
<generator class="increment"/>
</id>
<property name="balance" type="big_decimal" column="balance"/>
<property name="lastModified" type="timestamp" column="last_modified"/>
<list name="txns" table="transactions" inverse="true" cascade="all">
<key column="accountId" not-null="true"/>
<index column="transactionId"/>
<one-to-many class="com.joe.data.Transaction"/>
</list>
<many-to-one name="userId" class="User" column="userid" not-null="true"
unique="true" cascade="all"/>
<many-to-one name="accountType" class="AccountType" column="account_type"
not-null="true" cascade="all" unique="true" />
</class>
<class name="Transaction" table="transactions">
<id name="transactionId" column="transactionid">
<generator class="increment"/>
</id>
<property name="description" column="description"/>
<property name="amount" type="big_decimal" column="amount"/>
<property name="dateAdded" column="date_added"/>
<property name="reoccuring" type="numeric_boolean" column="reoccuring"/>
<many-to-one name="category" class="Category" column="category"
not-null="true" cascade="all" unique="true" />
</class>
<class name="Category" table="categories">
<id name="categoryId" column="categoryid"/>
<property name="categoryName" column="categoryname" not-null="true"/>
</class>
<class name="AccountType" table="account_types">
<id name="accountType" column="account_type"/>
<property name="accountName" column="name"/>
</class>
If I leave inverse="true" on the list of accounts (in the User) I get the ConstraintViolationException because the userid is not getting put in the insert query. If I take inverse="true" off of the list of accounts, I get org.hibernate.MappingException: Repeated column in mapping for entity: com.joe.data.Account column: accountid (should be mapped with insert="false" update="false")
To clarify lowercase names are database columns names, camel case are class variable names. I know Transaction class isn't working quite right yet, but if I could get the Accounts to insert I could do the same thing to get the Transactions to insert.
Edit: I added the many-to-one on the Account class and now I am getting another exception where hibernate is complaining about missing a getter for userId in com.joe.data.Account
In order to get inverse="true" work, you need to define many-to-one for User in Account and for Account in Transaction class and mappings.

hibernate Criteria API many to many

TaskCategory.hbm.xml
<hibernate-mapping>
<class name="TaskCategory" table="TASK_CATEGORY" select-before-update="true">
<id name="taskCategoryId" type="integer">
<column name="TASK_CATEGORY_ID" />
<generator class="identity" />
</id>
<property name="taskCategory" type="string">
<column name="TASK_CATEGORY" length="512" not-null="true" />
</property>
<property name="taskCategoryGroup" type="string">
<column name="TASK_CATEGORY_GROUP" length="32" not-null="true" />
</property>
<property name="description" type="string">
<column name="DESCRIPTION" length="255" />
</property>
<set name="jurisdictions" inverse="true" table="task_category_jurisdiction">
<key>
<column name="task_category_id" not-null="true" />
</key>
<many-to-many entity-name="com.sterling.ag.model.Jurisdiction">
<column name="jurisdiction_ID" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
Jurisdiction.hbm.xml
<hibernate-mapping default-access="field">
<class name="Jurisdiction" table="Jurisdiction">
<id name="jurisdictionId" type="int">
<column name="Jurisdiction_ID" />
<generator class="identity" />
</id>
<many-to-one name="jurisdictionType" class="JurisdictionType" fetch="select">
<column name="Jurisdiction_Type_ID" not-null="true" />
</many-to-one>
<one-to-one name="flattenedJurisdiction" class="FlattenedJurisdiction" />
<set name="taskCategories" table="task_category_jurisdiction" fetch="select">
<key>
<column name="jurisdiction_id" not-null="true" />
</key>
<many-to-many entity-name="TaskCategory">
<column name="task_category_id" not-null="true" />
</many-to-many>
</set>
</class>
I want to achieve something like this:
whereClause.append(" and a.jurisdiction_id not in (select distinct (j.jurisdiction_id) from " +
"task_category_jurisdiction j)" );
There is another Hibernate file for "a" which contains jurisdiction. And where clause is a StringBuffer.
I have tried this:
DetachedCriteria dc1 = DetachedCriteria.forClass(TaskCategory.class);
dc1.setProjection(Projections.distinct(Projections.property("jurisdictions")));
criteriaQuery.add(Restrictions.not(Subqueries.in("a.jurisdiction", dc1)));

Categories

Resources