Exception in column using addJoin in Native SQL Hibernate - java

I'm using Hibernate 5.2.8, I have the tables Departamentos and Empleados. Departamentos.java
private int deptNo;
private String dnombre;
private String loc;
private Set<Empleados> empleadoses = new HashSet<Empleados>(0);
Empleados.java
private int empNo;
private Departamentos departamentos;
......
Departamentos HBM
<hibernate-mapping auto-import="true" default-access="property" default-cascade="none" default-lazy="true">
<class catalog="hibernate" dynamic-insert="false" dynamic-update="false" mutable="true" name="jdbc.Departamentos" optimistic-lock="version" polymorphism="implicit" select-before-update="false" table="departamentos">
<id name="deptNo" type="int">
<column name="dept_no"/>
<generator class="assigned"/>
</id>
.........
<set embed-xml="true" fetch="select" inverse="true" lazy="true" mutable="true" name="empleadoses" optimistic-lock="true" sort="unsorted" table="empleados">
<key on-delete="noaction">
<column name="dept_no" not-null="true"/>
</key>
<one-to-many class="jdbc.Empleados" embed-xml="true" not-found="exception"/>
</set>
</class>
Empleados HBM
<hibernate-mapping auto-import="true" default-access="property" default-cascade="none" default-lazy="true">
<class catalog="hibernate" dynamic-insert="false" dynamic-update="false" mutable="true" name="jdbc.Empleados" optimistic-lock="version" polymorphism="implicit" select-before-update="false" table="empleados">
<id name="empNo" type="int">
<column name="emp_no"/>
<generator class="assigned"/>
</id>
<many-to-one class="jdbc.Departamentos" embed-xml="true" fetch="select" insert="true" name="departamentos" not-found="exception" optimistic-lock="true" unique="false" update="true">
<column name="dept_no" not-null="true"/>
</many-to-one>
......
This is the query:
Query q = session.createSQLQuery("SELECT e.emp_no,e.apellido,e.oficio, d.dnombre FROM empleados e inner join departamentos d on e.dept_no=d.dept_no "
+ "where d.dnombre LIKE '"+dep+"'")
.addEntity("e",jdbc.Empleados.class)
//.addEntity("d",jdbc.Departamentos.class)
.addJoin("d","e.departamentos");
Exception:
ERROR: Column 'dept_no' not found. Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute query
How to resolve this problem?

Related

What is a proper way to delete a list of objects in Hibernate?

I have an object User, which has a List of UserDictionary. Each UserDictionary has a List of UserWords with cascade delete.
User.java
public class User implements Serializable
{
private Long id;
private String login;
private String password;
private String email;
private Boolean isVerified;
private List<UserDictionary> dictionaries = new ArrayList<>();
private UserTrainingSettings settings;
//getters and setters there
}
And mapping User.hbm.xml
<hibernate-mapping>
<class name="User" dynamic-insert="true" dynamic-update="true" table="USER" entity-name="user">
<id name="id" type="java.lang.Long" column="user_id">
<generator class="native"/>
</id>
<property name="login" type="java.lang.String" length="40" not-null="true" unique="true"/>
<property name="password" type="java.lang.String" length="32" not-null="true"/>
<property name="email" type="java.lang.String" length="100" not-null="true"/>
<property name="isVerified" type="java.lang.Boolean" column="verified" not-null="true"/>
<list name="dictionaries" fetch="join">
<key column="user_id" not-null="true" on-delete="cascade"/>
<one-to-many class="com.github.wordsmemoriser.Model.UserDictionary"/>
</list>
<one-to-one name="settings" class="com.github.wordsmemoriser.Model.UserTrainingSettings"
cascade="javax.persistence.CascadeType.REMOVE"/>
</class>
</hibernate-mapping>
UserDictionary.java
public class UserDictionary
{
private Long id;
private User user;
private String name;
private List<UserWords> words = new ArrayList<>();
//getters and setters there
}
And mapping UserDictionary.hbm.xml
<hibernate-mapping>
<class name="UserDictionary" dynamic-insert="true" dynamic-update="true" table="DICTIONARY">
<id name="id" type="java.lang.Long" column="dict_id">
<generator class="native"/>
</id>
<many-to-one name="user" class="com.github.wordsmemoriser.Model.User" fetch="join">
<column name="user_id" not-null="true"/>
</many-to-one>
<property name="name" type="java.lang.String" length="100"/>
<list name="words">
<key column="dict_id" not-null="true" on-delete="cascade"/>
<one-to-many class="com.github.wordsmemoriser.Model.UserWords"/>
</list>
</class>
</hibernate-mapping>
What is a proper way to delete all UserDictionaries from User? Should I iterate this list, delete every UserDictionary from database, then clear this list and update User like this
session.beginTransaction();
for(UserDictionary dict : user.getDictionaries())
{
session.delete(dict);
}
user.getDictionaries().clear();
session.update(user);
session.getTransaction().commit();
or should I just clear User's list and then update it like this
user.getDictionaries().clear();
session.beginTransaction();
session.update(user);
session.getTransaction().commit();

Hibernate simultaneous many-to-many and many-to-one mapping

I have a question about the creation of database schemes by Hibernate.
In our project we have users and groups. Groups have exactly one owner and can have multiple members. A user can be owner and member of multiple groups.
We came up with the following Hibernate mapping:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.User" table="ProductUser">
<id name="id" column="userId">
<generator class="native"/>
</id>
<property name="email"/>
<property name="firstName"/>
<property name="lastName"/>
<set name="ownedUserGroups" table="UserGroup" inverse="true">
<key column="userId"/>
<one-to-many class="model.UserGroup"/>
</set>
<set name="userGroups" table="Members" inverse="false" lazy="true" fetch="select">
<key column="userId"/>
<many-to-many column="userGroupId" class="model.UserGroup"/>
</set>
</class>
<class name="model.UserGroup" table="UserGroup">
<id name="id" column="userGroupId">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="owner" class="model.User" column="owner_UserId"/>
<set name="members" table="Members" inverse="true" lazy="true" fetch="select">
<key column="userGroupId"/>
<many-to-many column="userId" class="model.User"/>
</set>
</class>
</hibernate-mapping>
The database scheme Hibernate creates for us looks the following:
Database scheme created by Hibernate
Can somebody explain why usergroup has the userid as a foreign key? (As you can see in the image)
For the sake of completeness, here is the code for User and UserGroup:
public class User {
private int id;
private String firstName;
private String lastName;
private String email;
private Set<UserGroup> ownedUserGroups;
private Set<UserGroup> userGroups;
public User() {
this.ownedUserGroups = new HashSet<>();
this.userGroups = new HashSet<>();
}
public User(String firstName, String lastName, String email) {
this();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
// getters and setters
}
public class UserGroup {
private int id;
private String name;
private User owner;
private Set<User> members;
public UserGroup() {
this.members = new HashSet<>();
}
public UserGroup(String name, User owner, HashSet<User> members) {
this.name = name;
this.owner = owner;
this.members = members;
}
// getters and setters
}
Ok. The problem is with your many-to-one-mapping. What your doing is your trying to set ownedUserGroups to all the groups where the userId equals the id of the current user. However you need to look for all groups where the owner_UserId equals the id of your user. Basically you just need to replace userId with owner_UserId. Your final mapping file should look like this:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.User" table="ProductUser">
<id name="id" column="userId">
<generator class="native"/>
</id>
<property name="email"/>
<property name="firstName"/>
<property name="lastName"/>
<set name="ownedUserGroups" table="UserGroup" inverse="true">
<key column="owner_userid"/> <!-- CHANGED -->
<one-to-many class="model.UserGroup"/>
</set>
<set name="userGroups" table="Members" inverse="false" lazy="true" fetch="select">
<key column="userId"/>
<many-to-many column="userGroupId" class="model.UserGroup"/>
</set>
</class>
<class name="model.UserGroup" table="UserGroup">
<id name="id" column="userGroupId">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="owner" class="model.User" column="owner_UserId"/>
<set name="members" table="Members" inverse="true" lazy="true" fetch="select">
<key column="userGroupId"/>
<many-to-many column="userId" class="model.User"/>
</set>
</class>
</hibernate-mapping>

Hibernate org.hibernate.LazyInitializationException: could not initialize

I have two classes :
Etudiant and Pays
In the database the table Etudiant has a foreign key for the table Pays.
In my code I have something like this :
List<Etudiant> listEtudiants = (List<Etudiant>) etudiantService.getAll();
for(Etudiant etudiant : listEtudiants) {
if(((JTextField)arg0.getSource()).getText().equals(etudiant.getNom())){
System.out.println(etudiant.getPays().getNom());
}
}
but when I run this code it fails with the exception:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
In the line :
System.out.println(etudiant.getPays().getNom());
Mapping for Etudiant:
<hibernate-mapping>
<class name="tp.ihm.domain.Etudiant" table="etudiant" schema="public" optimistic-lock="version">
<id name="numInsc" type="java.lang.Long">
<column name="num_insc" />
<generator class="assigned" />
</id>
<many-to-one name="pays" class="tp.ihm.domain.Pays" fetch="select">
<column name="pays" not-null="true" />
</many-to-one>
<property name="nom" type="string">
<column name="nom" length="50" not-null="true" />
</property>
<property name="prenom" type="string">
<column name="prenom" length="50" not-null="true" />
</property>
</class>
</hibernate-mapping>
Mapping for Pays:
<hibernate-mapping>
<class name="tp.ihm.domain.Pays" table="pays" schema="public" optimistic-lock="version">
<id name="id" type="java.lang.Long">
<column name="id" />
<generator class="assigned" />
</id>
<property name="nom" type="string">
<column name="nom" length="45" not-null="true" />
</property>
<set name="etudiants" table="etudiant" inverse="true" lazy="true" fetch="select">
<key>
<column name="pays" not-null="true" />
</key>
<one-to-many class="tp.ihm.domain.Etudiant" />
</set>
</class>
</hibernate-mapping>
I tried to remove the fetch attribute in the mapping for Pays, and then to change it's value to eager but nothing works.
Could someone please help me with this ?
Edit :
This is the code for the getAll method :
public List getAll() throws EntityNotFoundException {
// Get the current session
Session s = getSession();
List list = null;
// If the BLL layer started a transaction
// In this case it is the BLL layer that manages the session and transaction
if (anActiveTransactionExist(s)) {
list = s.createCriteria(Etudiant).list();
} else {
LOGGER.debug("DAO initialize its own transaction");
Transaction tx = null;
try {
// Starts a transaction locally
tx = s.beginTransaction();
list = s.createCriteria(boClass).list();
tx.commit();
} catch (RuntimeException ex) {
// Cancel the transaction if there is a problem
handleDaoOpError(tx, ex);
} finally {
closeSession(s);
}
}
if (list == null || list.size() == 0)
throw new EntityNotFoundException();
return list;
}
You need to change the mapping of Etudiant from fetch=select to fetch=join
fetch-“join” = Disable the lazy loading, always load all the collections and entities.
fetch-“select” (default) = Lazy load all the collections and entities.
<many-to-one name="pays" class="tp.ihm.domain.Pays" fetch="join">
<column name="pays" not-null="true" />
</many-to-one>

Hibernate query to get records from three related tables

I have three objects USER, CONTACT and ACTION.
Each USER has many CONTACTS and each CONTACT has many ACTIONS
Each CONTACT and ACTION has status assigned to them, e.g. 20 or 60 or...
Please have a look at the data model.
Requirement is to get the CONTACTs having a particular status, or get the CONTACTs whose ACTIONs have that particular status.
E.g. get me CONTACTs with status 20, or CONTACTs who’s ACTIONs have status 20
At the moment I have the following query that is retrieving the CONTACTs with the status 20 and does not considers that status of the ACTIONs
USER
public class User {
private Integer userID;
private String userFirstName;
private String userLastName;
private Set<Contact> contactSet = new HashSet<Contact>();
private Set<Action> actionSet = new HashSet<Action>();
private ContactCriteria contactCriteria;
.
.
.
}
CONTACT
public class Contact implements Serializable {
private Integer contactID;
private Integer contactStatus = 0;
private String givenName;
private String familyName;
private String streetAddress;
private Set<User> userSet = new HashSet<User>();
private Set<Action> actionSet = new HashSet<Action>();
.
.
.
}
ACTION
public class Action implements Serializable {
private Integer actionID;
private Integer actionStatus;
private User user;
private String actionNote;
private Contact contact;
.
.
.
}
Following are my mapping files:
User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.smallworks.model" schema="smallworksdb">
<class name="User" table="USERACCOUNT">
<id column="USER_ID" length="500" name="userID">
<generator class="increment"/>
</id>
<property column="USER_FIRSTNAME" generated="never" lazy="false" length="100" name="userFirstName"/>
<property column="USER_LASTNAME" generated="never" lazy="false" length="100" name="userLastName"/>
<set cascade="all" fetch="select" lazy="true" name="contactSet" sort="unsorted" table="USER_CONTACT">
<key column="USER_ID"/>
<many-to-many class="com.smallworks.model.Contact"
column="CONTACT_ID" order-by="CONTACT_ID" unique="false"/>
</set>
<!-- one to many mapping with Action -->
<set inverse="true" lazy="true" name="actionSet" sort="unsorted" order-by="ACTION_DUE_DATE" cascade="save-update">
<key column="USER_ID"/>
<one-to-many class="com.smallworks.model.Action"/>
</set>
<!-- one to one mapping with ContactCriteria -->
<one-to-one name="contactCriteria" class="com.smallworks.model.ContactCriteria"
cascade="save-update" lazy="false"></one-to-one>
</class>
</hibernate-mapping>
Contact.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.smallworks.model" schema="smallworksdb">
<class name="Contact" table="CONTACT">
<id column="CONTACT_ID" length="500" name="contactID">
<generator class="increment"/>
</id>
<property column="GIVEN_NAME" generated="never" lazy="false"
length="100" name="givenName"/>
<property column="FAMILY_NAME" generated="never" lazy="false"
length="100" name="familyName"/>
<property column="STREET_ADDRESS" generated="never" lazy="false"
length="100" name="streetAddress"/>
<property column="CONTACT_STATUS" generated="never" lazy="false"
name="contactStatus" type="integer"/>
<set inverse="true" lazy="false" name="userSet" sort="unsorted" table="USER_CONTACT">
<key column="CONTACT_ID"/>
<many-to-many class="com.smallworks.model.User" column="USER_ID" unique="false"/>
</set>
<!-- one to many mapping with Action -->
<set inverse="true" lazy="true" name="actionSet" sort="unsorted" order-by="ACTION_DUE_DATE" cascade="save-update">
<key column="CONTACT_ID"/>
<one-to-many class="com.smallworks.model.Action"/>
</set>
</class>
</hibernate-mapping>
Action.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.smallworks.model" schema="smallworksdb">
<class name="Action" table="ACTION">
<id column="ACTION_ID" length="500" name="actionID">
<generator class="increment"/>
</id>
<property column="ACTION_STATUS" generated="never" lazy="false"
name="actionStatus" type="integer"/>
<!-- many to one mapping with Contact -->
<many-to-one cascade="save-update"
class="com.smallworks.model.Contact" column="CONTACT_ID" lazy="false"
name="contact" not-null="true" />
<!-- many to one mapping with User -->
<many-to-one class="com.smallworks.model.User" column="USER_ID"
lazy="false" name="user" not-null="true"/>
</class>
</hibernate-mapping>
My existing query is:
Query query = session.createQuery("select distinct c FROM com.smallworks.model.User as u INNER JOIN u.contactSet as c WHERE u.userID=:userIDPara AND c.contactStatus in (:contactStatusPara)");
query.setParameter("userIDPara", user.getUserID());
query.setParameterList("contactStatusPara", statusList);
contactList = query.list();
Add an outer join on c.actions as a and an OR restriction on a.status.
select distinct c FROM com.smallworks.model.User as u INNER JOIN u.contactSet as c LEFT OUTER JOIN c.actionSet a WHERE u.userID=:userIDPara AND (c.contactStatus in (:contactStatusPara) OR a.actionStatus in (: actionStatusPara)

Mapping same class relation

Hi
I’m trying to map some classes in hibernate there and have general problem how such mapping can be done.
There is User class and Facebook user class which has the following structure
User Class :
public class User{
public User(){}
Long Id;
String FirstName;
String LastName;
....
FbUser fbuser;
//// all requred
getters and setters...
}
Facebook class FbUser can have list of Friends which are objects of the same class FbUser.
public class FbUser{
public FbUser(){}
Long fbId;
String FirstName;
String LastName;
List<FbUser> friends;
//// all requred
getters and setters...
}
Till now I made many to one relation between User And FbUser.
<hibernate-mapping>
<class
name="User"
table="User"
>
<id
name="Id"
column="ID"
type="java.lang.Long"
unsaved-value="null"
>
<generator class="increment"/>
</id>
<property
name="FirstName"
update="true"
insert="true"
not-null="false"
unique="false"
type="java.lang.String"
>
<column name="FirstName" />
</property>
<property
name="LastName"
update="true"
insert="true"
not-null="false"
unique="false"
type="java.lang.String"
>
<column name="LastName" />
</property>
<many-to-one
name="fbUser"
class="FbUser"
cascade="all"
column="fbId"
unique="true"
/>
</class>
</hibernate-mapping>
And now the FbUser Mapping:
<hibernate-mapping>
<class
name="FbUser"
table="FbUser"
>
<id
name="fbId"
column="fbId"
type="java.lang.Long"
unsaved-value="null"
>
<generator class="increment"/>
</id>
<property
name="FirstName"
update="true"
insert="true"
not-null="false"
unique="false"
type="java.lang.String"
>
<column name="FirstName" />
</property>
<property
name="LastName"
type="java.lang.String"
update="true"
insert="true"
column="LastName"
not-null="true"
unique="false"
/>
</class>
</hibernate-mapping>
Chow can I map FbUser List inside the FbUser Map file? I got lost :(
You can create an additional class named, for instance, MyFriends
public class FbUser {
List<MyFriends> friends = new ArrayList<MyFriends>();
}
Just relevant part
If you have a index-column
<hibernate-mapping>
<class name="FbUser">
<list name="myFriends">
<key column="ME_ID" insert="false" update="false"/>
<list-index column="WHICH COLUMN SHOULD BE USED AS INDEX"/>
<one-to-many class="MyFriends"/>
</list>
</class>
</hibernate-mapping>
If you do not have a index-column
re-write your list as
public class FbUser {
Collection<MyFriends> friends = new ArrayList<MyFriends>();
}
And
<hibernate-mapping>
<class name="FbUser">
<bag name="columns">
<key column="ME_ID" insert="false" update="false"/>
<one-to-many class="MyFriends"/>
</bag>
</class>
</hibernate-mapping>
And your MyFriends mapping. Notice you need a composite primary key (implemented as a static inner class)
<class name="MyFriends">
<composite-id name="myFriendsId" class="MyFriends$MyFriendsId">
<key-property name="meId"/>
<key-property name="myFriendId"/>
</composite-id>
<many-to-one name="me" class="FbUser" insert="false" update="false"/>
<many-to-one name="myFriend" class="FbUser" insert="false" update="false"/>
</class>
Your MyFriends is shown as follows
public class MyFriends {
private MyFriendsId myFrinedId;
private FbUser me;
private FbUser myFriend;
public static class MyFriendsId implements Serializable {
private Integer meId;
private Integer myFriendId;
// getter's and setter's
public MyFriendsId() {}
public MyFriendsId(Integer meId, Integer myFriendId) {
this.meId = meId;
this.myFriendId = myFriendId;
}
// getter's and setter's
public boolean equals(Object o) {
if(!(o instanceof MyFriendsId))
return false;
MyFriendsId other = (MyFriendsId) o;
return new EqualsBuilder()
.append(getMeId(), other.getMeId())
.append(getMyFriendId(), other.getMyFriendId())
.isEquals();
}
public int hashcode() {
return new HashCodeBuilder()
.append(getMeId())
.append(getMyFriendId())
.hashCode();
}
}
}
Well, first: User has a one-to-one relation with FbUser, correct?
second: Map FbUser to FbUser as a many to many relation using a list or a set. I have an Set example here:
<set
name="friends"
table="FbUser" <!-You may use other table here if you want->
access="field">
<key
column="fbId"/>
<many-to-many
class="bla.bla.bla.FbUser"
column="friend_id" />
</set>

Categories