Here I am trying to create hibernet mapping between three tables.
atom stores user unique name and id, post_messages stores messages
likes is a table which store likes of messages by users(atom).
One user(atom) can like multiple messages.
and multiple user(atom) can like a single message.
one user can like a particular message once
Data in likes table will store whenever user(atom) click on like button of message(on jsp page)
My table structure are as given below
atom
CREATE TABLE `atom` (
`id` int(100) NOT NULL AUTO_INCREMENT,
`name` varchar(200),
`type` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
unique KEY (name)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
likes
CREATE TABLE likes (
messageid bigint(200) NOT NULL,
aid int(100) NOT NULL,
adddate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (messageid,aid),
CONSTRAINT messageid FOREIGN KEY (messageid) REFERENCES post_messages(messageid) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `aid` FOREIGN KEY (aid) REFERENCES atom (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
post_messages
CREATE TABLE `post_messages` (
`messageid` bigint(200) NOT NULL AUTO_INCREMENT,
`message` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`messageid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I want to create classes and hbm.xml file for above table
To solve above I have created classes according to tables as below
Atom
public class Atom implements java.io.Serializable {
private Integer id;
private String name;
private String type;
private Set postMessages=new Hashset(0);
//getter setter and constructor of above
}
PostMessages
public class PostMessages implements java.io.Serializable {
private Long messageid;
private String message;
private Set likes = new HashSet(0);
//getter setter and constructor of above
}
Likes
public class Likes implements java.io.Serializable {
private Long messageid;
private Integer aid;
private Atom atom;
private PostMessages postMessages;
private Date adddate;
//getter setter and constructor of above
}
Hibernate mapping files
Atom.hbm.xml
<hibernate-mapping>
<class name="hibernetMappings.Atom" table="atom" catalog="xrcwrn_sms">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="name" length="200" unique="true" />
</property>
<property name="type" type="string">
<column name="type" length="100" not-null="true" />
</property>
<set name="likes" table="likes" inverse="true" lazy="true" fetch="select">
<key>
<column name="aid" not-null="true" />
</key>
<one-to-many class="hibernetMappings.Likes" />
</set>
</hibernate-mapping>
PostMessages.hbm.xml
<hibernate-mapping>
<class name="hibernetMappings.PostMessages" table="post_messages" catalog="xrcwrn_sms">
<id name="messageid" type="java.lang.Long">
<column name="messageid" />
<generator class="identity" />
</id>
<property name="message" type="string">
<column name="message" length="1000" />
</property>
<property name="visibility" type="string">
<column name="visibility" length="100" />
</property>
<property name="totalLikes" type="java.lang.Long">
<column name="total_likes" />
</property>
<set name="likes" table="likes" inverse="true" lazy="true" fetch="select">
<key>
<column name="messageid" not-null="true" />
</key>
<one-to-many class="hibernetMappings.Likes" />
</set>
</hibernate-mapping>
Likes.hbm.xml
<hibernate-mapping>
<class name="hibernetMappings.Likes" table="likes" catalog="xrcwrn_sms">
<composite-id name="id" class="hibernetMappings.Likes">
<key-property name="messageid" type="long">
<column name="messageid" />
</key-property>
<key-property name="aid" type="int">
<column name="aid" />
</key-property>
</composite-id>
<many-to-one name="atom" class="hibernetMappings.Atom" update="false" insert="false" fetch="select">
<column name="aid" not-null="true" />
</many-to-one>
<many-to-one name="postMessages" class="hibernetMappings.PostMessages" update="false" insert="false" fetch="select">
<column name="messageid" not-null="true" />
</many-to-one>
<property name="adddate" type="timestamp">
<column name="adddate" length="19" not-null="true" />
</property>
</hibernate-mapping>
What changes should I do in above. To make it correct.
Related
Say I have three tables in a many-to-many: user, group, and user_in_group. The structure of the many-to-many is:
user_id BIGINT
group_id BIGINT
generate_table TINYINT
Which should result in:
public UserInGroup(UserInGroupId id = new UserInGroupId(user_id, group_id),
User user,
Group group,
boolean generateTable)
But instead, it results in:
public UserInGroup(UserInGroupId id = new UserInGroupId(user_id, group_id),
Group group,
User user,
boolean generateTable)
I thought it might be that the foreign key for group was created before the foreign key for user, but I swapped the foreign keys and it make no difference.
Here is my UserInGroup.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 Aug 1, 2014 10:06:06 AM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.my.project.UserInGroup" table="user_in_group" catalog="project">
<composite-id name="id" class="com.my.project.UserInGroupId">
<key-property name="UserId" type="long">
<column name="user_id" />
</key-property>
<key-property name="GroupId" type="long">
<column name="group_id" />
</key-property>
</composite-id>
<many-to-one name="Group" class="com.my.project.Group" update="false" insert="false" fetch="select">
<column name="group_id" not-null="true" />
</many-to-one>
<many-to-one name="User" class="com.my.project.User" update="false" insert="false" fetch="select">
<column name="user_id" not-null="true" />
</many-to-one>
<property name="generateTable" type="boolean">
<column name="generate_table" not-null="true" />
</property>
</class>
</hibernate-mapping>
The order of the properties in the generated constructors corresponds to the order of the properties within the XML Mapping.
In the mapping for the composite key, the userId is first, then the groupId. Hence you get new UserInGroupId(user_id, group_id). For the many-to-one references, it is vice-versa - the reference to the Group is stated first, then the reference to the User.
You can simply change the XML and switch the order of the many-to-one references:
<many-to-one name="User" class="com.my.project.User" update="false" insert="false" fetch="select">
<column name="user_id" not-null="true" />
</many-to-one>
<many-to-one name="Group" class="com.my.project.Group" update="false" insert="false" fetch="select">
<column name="group_id" not-null="true" />
</many-to-one>
Since the XML is generated from reverse engeneering, the database that you reverse engeneer probably returns the two foreign keys in the order that you see in the generated XML. If you do not want to manually change the XML, you should check, if you can modify the source database to return the columns in your desired order.
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.
I have a table Project with fields
ID
PROJECT_BASELINE_ATTRIBUTES_ID (FK for table PROJECT_BASELINE_ATTR)
This table has the following mapping
<hibernate-mapping package="com.initech.db.model">
<class name="com.initech.db.model.Project" table="PROJECT">
<id name="id" column="id" type="java.lang.Long">
<meta attribute="use-in-tostring">true</meta>
<generator class="sequence">
<param name="sequence">PROJECT_ID_SEQ</param>
</generator>
</id>
<many-to-one name="projectBaselineAttributes" column="PROJECT_BASELINE_ATTRIBUTES_ID" class="com.initech.db.model.ProjectBaselineAttributes" cascade="all" not-null="true">
<meta attribute="use-in-tostring">true</meta>
</many-to-one>^
</class>
</hibernate-mapping>
The respective Project.java class has the fields
private Long id;
private ProjectBaselineAttributes projectBaselineAttributes;
Furthermore, I have a table PROJECT_BASELINE_ATTR, containing the field
ID
The Hibernate mapping:
<hibernate-mapping package="com.initech.db.model">
<class name="com.initech.db.model.ProjectBaselineAttributes" table="PROJECT_BASELINE_ATTR">
<id name="id" column="id" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">PRO_BASE_ATTR_ID_SEQ</param>
</generator>
</id>
<set name="projects" table="PROJECT" inverse="true" lazy="true" fetch="select">
<key>
<column name="PROJECT_BASELINE_ATTRIBUTES_ID" precision="22" scale="0" not-null="true" />
</key>
<one-to-many class="com.initech.db.model.Project" />
</set>
</class>
</hibernate-mapping>
The respective ProjectBaselineAttributes.java class has the fields
private Long id;
private Set projects = new HashSet();
The current mapping is not ideal, as the relationship between the two tables is actually one-to-one, but in the ProjectBaselineAttributes I have a set of Projects, even though there is always one Projet for one ProjectBaseLineattributes. What should the mapping look like for ProjectBaselineAttributes so that I can get the associated Project "singularly", i.e. so that the class ProjectBaselineAttributes.java would look like this:
private Long id;
private Project project;
Here's the section of the Hibernate documentation which details how to map such a bidirectional one-to-one association using a foreign key.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
unique="true"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<one-to-one name="person"
property-ref="address"/>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
You can try the below mappings as told in this example.
In the parent bean,
<one-to-one name="one2oneSubA1" class="com.manu.hibernate.mappings.domain.ASub1" cascade="all"
property-ref="parent"/>
In the child bean,
<many-to-one name="parent"
class="com.manu.hibernate.mappings.domain.AMain" column="a_id"
unique="true" cascade="save-update" />
I have 3 tables:
Account
{
Long account_id; // primary key, alternate key field 1
Long client_id; // alternate key field 2
...
}
Admin
{
Long office_id; // primary key field 1
Long account_id; // primary key field 2
Long client_id;
}
Office
{
Long office_id; // primary key
...
}
So the Admin table references Account table by alternate key (of account_id, client_id). I try to write mapping for it but cant understand how.
I have now:
<class name="Account" table="Account">
<id name="id">
<column name="account_id" not-null="true"/>
</id>
<properties name="account_ak1" unique="true">
<property name="id" column="account_id" insert="false" update="false"/>
<property name="client" column="client_id" insert="false" update="false"/>
</properties>
<many-to-one name="client" class="Client" column="client_id" lazy="false" fetch="join"/>
...
</class>
<class name="Admin">
<composite-id name="id" class="KeyPair">
<key-many-to-one name="t1" class="Office" column="office_id" lazy="false"/>
<key-many-to-one name="t2" class="Account" lazy="false" column="account_id"/>
</composite-id>
<many-to-one name="account" class="Account" not-null="true" insert="false" update="false" lazy="false" fetch="join" property-ref="account_ak1">
<column name="account_id"/>
<column name="client_id"/>
</many-to-one>
</class>
The problem is that i cant set client_id in sql update/insert this way and i cant set only account_id to insert/update false neither within composite-id nor within many-to-one.
Also, i tried to include all the fields of Account in primary key.
<composite-id name="id" class="KeyPair">
<key-many-to-one name="t1" class="Office" column="office_id" lazy="false"/>
<key-many-to-one name="t2" class="Account" lazy="false"/>
<column name="account_id"/>
<column name="client_id"/>
</key-many-to-one>
</composite-id>
but key-many-to-one can reference only primary key of Account and does not accept property-ref.
How to solve this?
I'm sure there must be thousands of examples demonstrating this association but I can't seem to find one anywhere.
I have a one-many relationship from Parent-Child and a many-one relationship from Child-Parent:
class Parent {
private Long id;
private String name;
private List<Child> children;
}
class Child {
private Long id;
private String name;
private Parent parent;
}
I'm expecting to end up with 2 tables that look as follows:
Parent
- id : bigint
- name : varchar
Child
- id : bigint
- parent_id : bigint
- sequence : bigint
- name : varchar
Have I got the right idea? If so does anyone know what I need to put in my mapping file so that when a parent is deleted so too are it's children.
Thanks in advance.
James
Found the solution in the end although I don't understand why I need insert="false" and update="false":
<hibernate-mapping>
<class name="foo.Parent" table="Parent">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="java.lang.String" column="name" length="50" />
<list name="children" cascade="all">
<key column="parent_id" />
<index column="sequence" />
<one-to-many class="foo.Child" />
</list>
</class>
<class name="foo.Child" table="Child">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="java.lang.String" column="name" length="50" />
<many-to-one name="parent" class="foo.Parent" column="parent_id" insert="false" update="false" />
</class>
</hibernate-mapping>