Hibernate Mapping issue when lazily loading a Set of custom Objects - java

I have trying to read from my database using Hibernate but I am having a problem. Any help would be appreciated. It has to do with the fact that there is a set of Answers in a Question object and I'm not sure the implications this is having on the subject.
List<Question> questions = session
.createQuery("from Question where topic = :id")
.setParameter("id", topic)
.list();
Code:
<class name="cdd.model.Question" table="question">
<id column="question_id" name="questionID" type="org.hibernate.type.PostgresUUIDType">
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
<many-to-one class="cdd.model.User" column="submitted_by" name="submittedBy" not-null="true" lazy = "false"/>
<many-to-one class="cdd.model.Topic" column="question_topic" name="topic" not-null="true" lazy = "false"/>
<property column="title" name="title" type="org.hibernate.type.TextType"/>
<property column="correct_answer" name="correctAnswer" type="org.hibernate.type.TextType"/>
<property column="date_submitted" name="dateSubmitted" type="org.hibernate.type.TimestampType"/>
<property column = "approved" name = "approved" type = "org.hibernate.type.BooleanType"/>
<set cascade="all" name="answers" >
<key column="question_id" not-null="true" lazy = "false" />
<one-to-many class="cdd.model.Answer"/>
</set>
</class>
Java Class That was mapped:
public class Question {
UUID questionID;
User submittedBy;
Topic topic;
String title;
String correctAnswer;
Timestamp dateSubmitted;
boolean approved;
Set<Answer> answers;
/*Constructor, Getters and Setters*/
}
Error:
XML validation started.
Checking file:/Users/rhamblin/Desktop/CDDExamGen/src/hibernateMapping.hbm.xml...
Attribute "lazy" must be declared for element type "key". [69]
XML validation finished.

Related

Hibernate Error indexing: null when checking if row exists

I am trying to check if a row exists in my database.
Word word = (Word) session.createQuery("select 1 from Word w where w.content = :key").setParameter("key",words[i]).uniqueResult();
I'm also trying:
Word word = session.get(Word.class,contentId);
Besides that I tried session.load,and some others. Everytime Hibernate returns error:
Error indexing: null
or
Error indexing: no row with the given identifier exists.
It is true, row does not existing but why doesn't it just returns null like it should for session.get:
http://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/Session.html#get(java.lang.Class,%20java.io.Serializable).
In case of not finding a row I wanted to create one and add to a database but I'm not able to check if it exists.
EDIT:
Word.java
public class Word {
private String content;
private Set<Sentence> sentences;
empty constructor, setters and getters
}
Word.hbm.xml
<class name="Word">
<id name="content" column="wordId" type="string">
</id>
<set name="sentences" inverse="true">
<key><column name="wordId"/></key>
<many-to-many class="Sentence" column="sentenceId"/>
</set>
</class>
Sentence.java
public class Sentence {
private long id;
private ProcessedUrl processedUrl;
private List<Word> words;
empty constructor, setters and getters
}
Sentence.hbm.xml
<class name="Sentence">
<id name="id" column="sentenceId">
<generator class="native"/>
</id>
<many-to-one name="processedUrl" column="processedUrlId" not-null="true"/>
<list name="words">
<key>
<column name="sentenceId" not-null="true"/>
</key>
<list-index column="idx" />
<many-to-many class="Word">
<column name="wordId" not-null="true"/>
</many-to-many>
</list>
</class>

Hibernate Criteria API where clause in many to many relation

I have relation many to many with extra fileds in linking table(mapping in xml files). Using criteria api how to add restrictions to name of product?
public class Recipe implements Serializable{
private int id_re;
private String name;
private Set<ProductRecipe> listOfRecipe_Product = new HashSet<>(0);
}
public class ProductRecipe implements Serializable{
private ProductRecipeMapping id;
private float quantity;
}
public class ProductRecipeMapping implements Serializable{
private Product product;
private Recipe recipe;
}
public class Product implements Serializable{
private int id_p;
private String name;
}
Mapping:
<class entity-name="recipe" name="Recipe" table="recipe">
<id name="id_re" type="java.lang.Integer">
<column name="id_re" />
<generator class="identity" />
</id>
<set name="listOfRecipe_Product" table="recipe_product" lazy="false" fetch="select" cascade="all">
<key>
<column name="id_re" not-null="true" />
</key>
<one-to-many entity-name="productRecipe" />
</set>
</class>
<class entity-name="productRecipe" name="ProductRecipe" table="recipe_product">
<composite-id name="id" class="ProductRecipeMapping" >
<key-many-to-one name="recipe" entity-name="recipe" column="id_re" />
<key-many-to-one name="product" entity-name="product" column="id_p" />
</composite-id>
<property name="quantity" type="float" column="quantity" />
</class>
<class entity-name="product" name="Product" table="product">
<id name="id_p" type="java.lang.Integer" column="id_p">
<generator class="identity" />
</id>
<property name="name" column="name" type="java.lang.String" not-null="true" length="255"/>
</class>
E.G. I use criteria for get recipe with name test:
Criteria cr = session.createCriteria(Recipe.class);
cr.add(Restrictions.eq("name", "test"));
but I don't know to get all recipes with list name of products
something like cr.add(Restrictions.eq("product.name", "test")); (but not work)
I use 2 idea to resolve this problem but nothing work:
1) Restrictions.eq("listOfRecipe_Product.id.product.name", "test")
but i get error org.hibernate.QueryException: could not resolve property: listOfRecipe_Product.id.product.name of: recipe
2)
cr.createCriteria("listOfRecipe_Product")
.createCriteria("id")
.createCriteria("product")
.add(Restrictions.eq("name", "test"));
I get error org.hibernate.QueryException: Criteria objects cannot be created directly on components. Create a criteria on owning entity and use a dotted property to access component property: listOfRecipe_Product.id
You will need to create aliases in order to add constraints to mapped entities;
e.g.:
Criteria cr = session.createCriteria(Recipe.class)
.createAlias("listOfRecipe_Product", "listOfRecipe_Product")
.createAlias("listOfRecipe_Product.id", "id")
.createAlias("id.product", "product")
.add(Restrictions.eq("product.name", "test"));

Hibernate many-to-many data retrieval

I have two objects User and Contact, with many to many relation, and I am using an intermediate table for this relation USER_CONTACT
Saving the data in this association is fine, but the retrieval is an issue.
I need to retrieve the data based on the User, but what I am getting is all the Contacts, for all the Users.
It will be good if you can let me know what wrong I am doing.
public class User {
private Integer userID;
private String userLoginEmail;
private String password;
private Set<Contact> contactSet = new HashSet<Contact>();
.
.
}
public class Contact implements Serializable {
private Integer contactID;
private String givenName;
private String familyName;
private Set<User> userSet = new HashSet<User>();
.
.
}
User.hbm.xml:
<class name="User" table="USERACCOUNT">
<id column="USER_ID" length="500" name="userID">
<generator class="increment" />
</id>
<property column="USER_LOGIN_EMAIL" generated="never" lazy="false" length="100" name="userLoginEmail" />
<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 name="contactSet" table="USER_CONTACT" inverse="false" lazy="false" fetch="select" cascade="all">
<key column="USER_ID"/>
<many-to-many column="CONTACT_ID" class="com.smallworks.model.Contact"/>
</set>
</class>
Contact.hbm.xml
<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"/>
<!-- many to many mapping with the User via User_Contact table -->
<set inverse="true" lazy="false" name="userSet" sort="unsorted" table="USER_CONTACT">
<key column="USER_ID"/>
<many-to-many class="com.smallworks.model.Contact" column="CONTACT_ID" unique="false"/>
</set>
</class>
and this is how I am trying to retrieve the data, which I think is not correct.
List contactList = session.createQuery("from Contact").list();
It will be good if I can know how to go about getting the Contacts based on the User.
// First, retrieve the user you want.
User user = (User) session.get(User.class, user_id_you_want);
// Second, get the contacts of that given user and add them to a list (optional)
List contacts = new ArrayList();
contacts.addAll(user.getContactSet());
return contacts;

Hibernate One-to-many HashMap not updating on child

I have the following parent object which maps to a table in my database:
public Parent {
private Long id;
private String mid;
private Integer days;
private BigDecimal fee;
private DateTime createdDate = new DateTime();
private DateTime lastModifiedDate;
private Map<String, Child> children;
}
With the following .hbm.xml:
<hibernate-mapping default-access="field">
<class name="Parent" table="parent_table">
<id column="id" length="50" name="id" unsaved-value="null">
<generator class="increment"/>
</id>
<property length="50" name="mid"/>
<property name="days"/>
<property name="fee"/>
<property name="createdDate" type="(...)PersistentDateTime"/>
<property name="lastModifiedDate" type="(...)PersistentDateTime"/>
<map cascade="all-delete-orphan" inverse="true" name="children" >
<key column="parentId" />
<map-key column="country" type="string" />
<one-to-many class="Child" />
</map>
</class>
</hibernate-mapping>
The child object is as follows:
public class Child implements Serializable {
private Long parentId;
private String country;
private String cu;
}
With the following .hbm.xml:
<hibernate-mapping default-access="field">
<class name="Child" table="child_table">
<composite-id>
<key-property name="parentId"/>
<key-property name="country"/>
<key-property name="cu"/>
</composite-id>
</class>
</hibernate-mapping>
After acquiring a Parent object from my db via:
getSession().createCriteria(Parent.class)
.add(Restrictions.eq("mid", mid))
.uniqueResult();
After making some changes to Child.cu in the children map I call a saveOrUpdate on the Parent object. After doing so all appears to save / update fine but upon checking the child_table in the db, these changes have not been saved / updated.
I believe this has something to do with the mappings of the map in the Parent class but can't seem to figure it out. Any help would be appreciated.
Thanks in advance.
If I understand correctly, you're modifying a field which is part of the primary key of your entity. This is illegal: the ID should be immutable.
My advice is to follow the good practices: use a non-composite, purely technical, auto-generated primary key. Everything will be much simpler (and also faster).

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