I have a class called product here is the definition
public class Product {
private String productId;
private Set<Label> name;
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public Set<Label> getName() {
return name;
}
public void setName(Set<Label> name) {
this.name = name;
}
}
i want the property called name to be retrieved via a select statement so I added this in my mapping file.
<class name="Product" table="PRODUCT">
<id name="productId" type="java.lang.String">
<column name="PRODUCTID" />
<generator class="assigned" />
</id>
<set name="name" cascade="all" inverse="true" lazy="false">
<key column="CONTENTID" />
<one-to-many class="com.dbs.web.models.org.Label" />
<loader query-ref="nameLabel" />
</set>
</class>
<sql-query name="nameLabel">
<load-collection alias="lbl" role="Product.name" />
SELECT {lbl.*} FROM LABEL lbl where lbl.CONTENTID = :productId and
lbl.KEY ='name'
</sql-query>
So all this works well. I am just a little worried that it would not perform very well. Its not like there will be thousands of record return by the sql-query it might be like 10.
Is there another way that this can be achieved.
Related
I'm trying to create a one to many relation between two tables. TestCase has a FK called Type
Basically many testCases can have one type but a testCase can only have one type.
What am I missing here?
TestCase table
TestType table
But I'm getting
Unkown column idtestType in field list
Model
public class TestCase {
private int id;
private String name;
private TestType type;
private byte[] data;
private String creationDate;
private String createdBy;
public TestCase() {
}
public TestCase(String name, TestType type, byte[] data, String creationDate, String createdBy) {
this.name = name;
this.type = type;
this.data = data;
this.creationDate = creationDate;
this.createdBy = createdBy;
}
TestCase.xml
<hibernate-mapping>
<class name="com.atp.Model.TestCases.TestCase" table="testCases">
<meta attribute="class-description">
This class contains the testCases details.
</meta>
<id name="id" type="int" column="idtestCase">
<generator class="native"/>
</id>
<property name="name" column="name" type="string"/>
<many-to-one name="type" class="com.atp.Model.TestCases.TestType" fetch="select">
<column name="idtestType"/>
</many-to-one>
<property name="data" column="data" type="binary"/>
<property name="creationDate" column="creationDate" type="string"/>
<property name="createdBy" column="createdBy" type="string"/>
</class>
</hibernate-mapping>
Model
public class TestType {
private int id;
private String desc;
private Set<TestCase> testCases = new HashSet<>(0);
public TestType() {
}
public TestType(String desc, Set<TestCase> testCases) {
this.desc = desc;
this.testCases = testCases;
}
TestType.xml
<hibernate-mapping>
<class name="com.atp.Model.TestCases.TestType" table="testType">
<meta attribute="class-description">
This class contains the testCases details.
</meta>
<id name="id" type="int" column="idtestType">
<generator class="native"/>
</id>
<property name="desc" column="desc" type="string"/>
<set name="testCases">
<key>
<column name="idtestType" />
</key>
<one-to-many class="com.atp.Model.TestCases.TestCase" />
</set>
</class>
</hibernate-mapping>
Trying to add it to the database
public static void addTestCase(String testName, String type, MultipartFile file, String createdBy) {
byte[] data;
Date date = new Date();
final DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
String creationDate = sdf.format(date);
TestType testType = new TestType();
testType.setDesc(type);
try {
data = file.getBytes();
TestCase testCase = new TestCase(testName,testType,data,creationDate,createdBy);
testType.getTestCases().add(testCase);
Database.addToDatabase(testCase);
} catch (IOException e) {
e.printStackTrace();
}
}
You're missing a
idtestType
column in the TestCase table.
Or, if you want to use the type column in the existing table your TestCase.xml-Mapping is wrong and should be
<many-to-one name="type" class="com.atp.Model.TestCases.TestType" fetch="select">
<column name="type"/>
</many-to-one>
(column is "type" instead of "idtestType")
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>
I have the following structure in my database:
I've mapped them in hibernate configuration files like this:
<hibernate-mapping>
<class name="model.CartEntity" table="cart">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<set name="products" table="cart_product_record"
inverse="true" lazy="false" fetch="select" cascade="save-update, delete">
<key>
<column name="cart_id" not-null="false" />
</key>
<one-to-many class="model.ProductRecordEntity" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="model.ProductRecordEntity" table="product_record">
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<many-to-one name="product" class="model.ProductEntity" fetch="select" cascade="save-update, delete">
<column name="product_id" />
</many-to-one>
<many-to-one name="cart" class="model.CartEntity" fetch="select" cascade="save-update, delete">
<column name="cart_id" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="model.ProductEntity" table="product">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<set name="productRecords" table="product_record_product" inverse="true"
lazy="false" fetch="select" cascade="save-update, delete">
<key>
<column name="product_id" not-null="true" />
</key>
<one-to-many class="model.ProductRecordEntity" />
</set>
</class>
</hibernate-mapping>
I retrieve from the database the cart which has all the product records, no problem so far, I get all the necessary data correctly.
CartEntity cart = findById(id);
List<ProductRecordEntity> productRecords = cart.getProductRecords();
The problem is when I try to get the product from the product record:
for (ProductRecordEntity productRecord: productRecords){
ProductEntity product = productRecord.getProduct();
}
I get an object with all fields with their default value, not the information from database.
When saving the entities in the database, the ids are populated correctly.
Product record table:
And the product table:
These are the entities:
public class CartEntity {
private int id;
private Set<ProductRecordEntity> products = new HashSet<ProductRecordEntity>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Set<ProductRecordEntity> getProducts() {
return products;
}
public void setProducts(Set<ProductRecordEntity> products) {
this.products = products;
}
}
public class ProductRecordEntity {
private int id;
private CartEntity cart;
private ProductEntity product;
public CartEntity getCart() {
return cart;
}
public void setCart(CartEntity cart) {
this.cart = cart;
}
public ProductEntity getProduct() {
return product;
}
public void setProduct(ProductEntity product) {
this.product = product;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public class ProductEntity implements Serializable{
private int id;
private Set<ProductRecordEntity> productRecords;
public Set<ProductRecordEntity> getProductRecords() {
return productRecords;
}
public void setProductRecords(Set<ProductRecordEntity> productRecords) {
this.productRecords = productRecords;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
This is the order of operations on the database:
persist(cartEntity);
persist(productEntity);
productRecordEntity.setCartEntity(cartEntity);
cartEntity.getProducts().add(productRecordEntity);
productRecordEntity.setProduct(productEntity);
persist(productRecordEntity);
productEntity.getProductRecords().add(productRecordEntity);
update(productEntity);
update(cartEntity);
Any idea what I'm missing? I can't find where the problem is, I've double, triple checked everything.
for CartEntity and ProductEntity mapping, why are you using association tables? you should use table="product_record".
I fixed it by adding lazy="false" to the ProductOrder xml mapping.
<hibernate-mapping>
<class name="model.ProductOrderEntity" table="product_order">
<id name="id" type="int" column="product_order_id">
<generator class="native" />
</id>
<property name="quantity" column="quantity" type="int" />
<property name="price" column="price" type="java.lang.Float" />
<many-to-one name="product" class="model.ProductEntity"
fetch="select" lazy="false">
<column name="product_id" not-null="true" />
</many-to-one>
<many-to-one name="order" class="model.OrderEntity"
fetch="select" lazy="false">
<column name="order_id" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
I think it's an initialization problem, when getting the product records from the database I should initialize the product field while the session is still opened, like this:
Hibernate.initialize(product);
i have three entity and Main(User) enitiy is in relation with other two entity,how can i retrive list of three entities from database in one query using hibernate
package hib.test;
import java.util.HashSet;
import java.util.Set;
public class Country {
private Integer id;
private String country;
private Set<User> userList = new HashSet<User>();
public Country() {
super();
// TODO Auto-generated constructor stub
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Set<User> getUserList() {
return userList;
}
public void setUserList(Set<User> userList) {
this.userList = userList;
}
}
User.java
package hib.test;
public class User {
private Integer id;
private UserType userType;
private Country country;
public User() {
super();
// TODO Auto-generated constructor stub
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public UserType getUserType() {
return userType;
}
public void setUserType(UserType userType) {
this.userType = userType;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
}
UserType.java
package hib.test;
import java.util.HashSet;
import java.util.Set;
public class UserType {
private Integer id;
private String userType;
private Set<User> userList = new HashSet<User>();
public UserType() {
super();
// TODO Auto-generated constructor stub
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public Set<User> getUserList() {
return userList;
}
public void setUserList(Set<User> userList) {
this.userList = userList;
}
}
country.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">
<!-- Generated Jun 6, 2012 1:12:01 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="hib.test.Country" table="COUNTRY">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="assigned" />
</id>
<property name="country" type="java.lang.String">
<column name="COUNTRY" />
</property>
<set name="userList" table="USER" inverse="false" lazy="true">
<key>
<column name="ID" />
</key>
<one-to-many class="hib.test.User" />
</set>
</class>
</hibernate-mapping>
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">
<!-- Generated Jun 6, 2012 1:12:01 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="hib.test.User" table="USER">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="assigned" />
</id>
<many-to-one name="userType" class="hib.test.UserType" fetch="join">
<column name="USERTYPE" />
</many-to-one>
<many-to-one name="country" class="hib.test.Country" fetch="join">
<column name="COUNTRY" />
</many-to-one>
</class>
</hibernate-mapping>
usertype.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">
<!-- Generated Jun 6, 2012 1:12:01 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="hib.test.UserType" table="USERTYPE">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="assigned" />
</id>
<property name="userType" type="java.lang.String">
<column name="USERTYPE" />
</property>
<set name="userList" table="USER" inverse="false" lazy="true">
<key>
<column name="ID" />
</key>
<one-to-many class="hib.test.User" />
</set>
</class>
</hibernate-mapping>
How can i retrive List<User>, List<Country> and List<UserType> with one query
EDIT
public static List<UserType> getUserTypeList() {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
List<UserType> list = null;
try {
transaction = session.beginTransaction();
list = session.createQuery("from UserType as u").list();
if (list != null) {
for (UserType uType : list)
Hibernate.initialize(uType.getUserList());
}
transaction.commit();
} catch (Exception e) {
if (transaction != null)
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
return list;
}
Actually I have 1 JTable and Two combo box each for UserType and Country
So when i select any data in combo box JTable data should be filter according to selected value and in memory it shoud be save selected UserType and Country object.
if you want relational data at once and memory is not an issue, do lazy="false"
try defining fetch type to EAGER on you user mapping, that way when you load your user it will load the country and userType.
You need three queries to do that:
select u from User u;
select ut from UserType ut;
select c from Country c;
EDIT:
If what you actually want is a list of all the user types, with the users of each user type, and the country of each user of each user type, all this loaded in a single query, then you need fetch joins, as explained in the Hibernate documentation:
select userType from UserType userType
left join fetch userType.users user
left join fetch user.country
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>