Foreign key in compiste primary key (duplicated column error) - java

We are just integrating Hibernate in our web application which has been developed since today using direct queries to a relational database.
We have generated hbm.xml files in order to have all the entities and mappings implemented for accessing database via hibernate for reading and writing.
The thing is that our schema has many composite primary keys and, because of that, we have a lot of foreign keys refering to those composite ids.
Above you can see an example of database schema in which we are having many problems. There is also the hbm.xml file:
<class name="Profile" table="Profile" optimistic-lock="version">
<id name="profileId" type "java.lang.Integer">
<column name="profileId" />
<generator class="assigned" />
</id>
<many-to-one name="location" class="Location" fetch="select" >
<column name="locationId" length="3" not-null="true" />
</many-to-one>
<many-to-one name="users" class="Users" fetch="select">
<column name="locationId" length="3" not-null="true" />
<column name="userId" length="30" not-null="true" />
</many-to-one>
<many-to-one name="groupUsers" class="GroupUsers" fetch="select">
<column name="locationId" length="3" not-null="true" />
<column name="groupUserId" length="30" not-null="true" />
</many-to-one>
</class>
<class name="Users" table="Users" optimistic-lock="version">
<composite-id name="id" class="UsersId">
<key-property name="locationId" type="string">
<column name="locationId" length="3" />
</key-property>
<key-property name="userId" type="string">
<column name="userId" length="30" />
</key-property>
</composite-id>
<set name="profiles" table="Profile" inverse="true" lazy="true" fetch="select">
<key>
<column name="locationId" length="3" not-null="true" />
<column name="userId" length="30" not-null="true" />
</key>
<one-to-many class="Profile" />
</set>
</class>
<class name="GroupUsers" table="GroupUsers" optimistic-lock="version">
<composite-id name="id" class="GroupUsersId">
<key-property name="locationId" type="string">
<column name="locationId" length="3" />
</key-property>
<key-property name="groupUserId" type="string">
<column name="groupUserId" length="30" />
</key-property>
</composite-id>
<set name="profiles" table="Profile" inverse="true" lazy="true" fetch="select">
<key>
<column name="locationId" length="3" not-null="true" />
<column name="groupUserId" length="30" not-null="true" />
</key>
<one-to-many class="Profile" />
</set>
</class>
<class name="Location" table="Location" optimistic-lock="version">
<id name="locationId" type="string">
<column name="locationId" length="3" />
<generator class="assigned" />
</id>
<set name="profiles" table="Profile" inverse="true" lazy="true" fetch="select">
<key>
<column name="locationId" length="3" not-null="true" />
</key>
<one-to-many class="Profile" />
</set>
</class>
When starting Tomcat I get the following error: "Profile column: locationId (should be mapped with insert="false" update="false")"
But if I try to put this two attributes in the many-to-one relation of the Profile.hbm.xml file, I can't insert a profile instance to the database (no effect):
<many-to-one name="location" class="Location" fetch="select" insert="false" update="false">
<column name="locationId" length="3" not-null="true" />
</many-to-one>
<many-to-one name="users" class="Users" fetch="select"insert="false" update="false">
<column name="locationId" length="3" not-null="true" />
<column name="userId" length="30" not-null="true" />
</many-to-one>
<many-to-one name="groupUsers" class="GroupUsers" fetch="select" insert="false" update="false">
<column name="locationId" length="3" not-null="true" />
<column name="groupUserId" length="30" not-null="true" />
</many-to-one>
Can anyone help me, please?
Thank you very much in advance.

Because you say you have many composite primary keys in a existing schema with data in it and you want to add hibernate to it.
That sounds like you rather would have no composite primary keys.
Just a thought:
I think it would not be such a big thing to drop your existing combined primary keys, make them uniqe indices instead and create new non combined primary keys updating all your data with a sequence (depending on the DMBS you are using).
That of course depends on how you want to integrate hibernate. There could be reasons of keeping the old combined primary keys.
But maybeyou should think about it.

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 - load children

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.

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.

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