Use join into hibernate mapping against main class foreing key - java

This is a simple description of my situation and the requirement I am not able to implement:
I have two tables "address" and "person" related with a FK:
CREATE TABLE `address` (
`id_address` int(11) NOT NULL,
`street` varchar(250) DEFAULT NULL,
`city` varchar(250) DEFAULT NULL,
PRIMARY KEY (`id_address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `person` (
`id_person` int(11) NOT NULL,
`name` varchar(250) DEFAULT NULL,
`id_sent_address` INT(11) NOT NULL,
PRIMARY KEY (`id_person`),
CONSTRAINT `fkSentAddress` FOREIGN KEY (`id_sent_address`) REFERENCES `address` (`id_address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And I want to create a hibernate mapping using this two tables to create a simple model.
It is important the fact that I NEED to do the mapping using "join" having something like this:
<class name="xxx.PersonAndAddress" table="person">
<id name="idPerson" type="java.lang.Integer">
<column name="id_person" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String" column="name"/>
<join table="address">
<key column="id_address" />
<property name="street" column="street" />
<property name="city" column="city" />
</join>
</class>
This is not working because the "join" key column "id_address" is creating the mapping against the primary key "id_person", and I don't know how can I change this behaviour column to use the person's "id_sent_address" instead "id_person". Is there any solution?
As I said, this is a simple situation that describes my real problem, which involves more fields and more logic, but this is the essence of the issue.
Right now I'm using formulas for each address's field but it is a big quantity of fields and I would use join to improve its performance.
Thanks a lot!

Two things, first of all, ORDER MATTERS. You need to create your address table first, before you can create your person table, as person table's id_sent_address DEPENDS on the id_address from address table.
Secondly, to set up a foreign key, the target key MUST be a key as well, which you forgot to add.
So once the two errors are fixed like below, you should be able to execute it without errors.
CREATE TABLE `address` (
`id_address` int(11) NOT NULL,
`street` varchar(250) DEFAULT NULL,
`city` varchar(250) DEFAULT NULL,
PRIMARY KEY(`id_address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `person` (
`id_person` int(11) NOT NULL,
`name` varchar(250) DEFAULT NULL,
`id_sent_address` INT(11) NOT NULL,
PRIMARY KEY (`id_person`),
CONSTRAINT `fkSentAddress` FOREIGN KEY (`id_sent_address`) REFERENCES `address` (`id_address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Related

Hibernate not persisting foreign keys in Mysql

I have an entity Property which has city field. Something like this:
#Entity
class Property {
...
#ManyToOne(fetch = FetchType.LAZY)
private City city;
...
}
So each property (e.g house or apartment) belongs to only one city.
Now here is a thing, if I try to log generated SQL by Hibernate, it is generating the foreign key in a right way:
Hibernate:
alter table property
add constraint FKdn1hnohufcwdr4a401xabcjn
foreign key (city_id_city)
references city (id_city)
However, if I check my Mysql database, there is no foreign key there, only index is generated:
show create table property;
leads to:
| property | CREATE TABLE `property` (
`id_property` int(11) NOT NULL AUTO_INCREMENT,
`created_at` datetime NOT NULL,
`deal_type` varchar(15) NOT NULL,
`publisher_type` varchar(15) NOT NULL,
`type` varchar(15) NOT NULL,
`updated_at` datetime NOT NULL,
`city_id_city` int(11) DEFAULT NULL,
PRIMARY KEY (`id_property`),
KEY `FKdn1hnohufcwdr4a401xabcjn` (`city_id_city`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
So the question is why there is no CONSTRAINT FOREIGN KEY () REFERENCES definition in my database?
The problem ended up to be the database engine after I switched to InnoDB engine it started working, as MyISAM does not implement foreign keys.
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
The annotation #ManyToOne is used to map two tables that have a relationship instance by a foreign key, it could not automatically create a foreign key in your database
You need to define the list Property in the City Entity and add the relationship there as well

How to exclude many-to-one relationship using hibernate reverse engineering?

I've two tables user and patient. Patient have a user id in it i.e user_id F.K to user.id.
When I create a model classes using reverse engineering, in User model it create Set but in that I need only Patient. My business model says one-to-one relationship between user & patient.
so is there a way to do it ?
Below is table schema.
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `Unique_Email_Id` (`user_email`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `patient` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `PATIENT_EMAIL_ID_UNIQUE_ID` (`email_id`),
UNIQUE KEY `UNIQUE_USER_ID` (`user_id`),
CONSTRAINT `User_Id_Foreign_Key_To_Patient_Id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
hibernate.reveng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd" >
<hibernate-reverse-engineering>
<type-mapping>
<sql-type jdbc-type="BIT" hibernate-type="int"></sql-type>
</type-mapping>
<table-filter match-name="user">
<table-filter match-name="patient"></table-filter>
<table name="patient">
<foreign-key constraint-name="Unique_user_Id">
<many-to-one exclude="true"/>
</foreign-key>
</table>
</hibernate-reverse-engineering>
I have solved the problem using a personalized strategy. For this we have to follow the following steps:
1-New dependence on maven:
<!-- Hibernate tools para estrategia presonalizada -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-tools</artifactId>
<version>5.3.7.Final</version>
</dependency>
2-Create custom strategy class (CustomReverseEngineeringStrategy) extending from DelegatingReverseEngineeringStrategy.
package com.xxx.model.strategy;
import java.util.List;
import org.hibernate.cfg.reveng.DelegatingReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.TableIdentifier;
public class CustomReverseEngineeringStrategy extends DelegatingReverseEngineeringStrategy {
...
}
3-Overwrite excludeForeignKeyAsManytoOne method, where we will set a criteria based on which we will indicate which manytoone relationships must be taken into account and which ones are not:
#Override
public boolean excludeForeignKeyAsManytoOne(String keyname, TableIdentifier fromTable, List<?> fromColumns, TableIdentifier referencedTable, List<?> referencedColumns) {
return referencedTable.getName().startsWith(EXCLUDED_REFERED_TABLE_PREFIX);
}
4-Adapt the configuration 'hibernate code generation' to make use of the customized strategy:
Unfortunately, the exclude annotation does not seem to work.
I hope this solution is useful. Using the personalized strategy can achieve many things because we can overwrite multiple methods that control almost all aspects of the reverse generation of entities.

Hibernate #ManyToOne mapping error

Good day to you. I have 2 tables.
CREATE TABLE A(
id NUMBER(10) NOT NULL,
name VARCHAR2(255) NULL,
category VARCHAR2(255) NULL,
is_hidder NUMBER(1) NULL,
is_enabled NUMBER(1) NULL,
b_id NUMBER(10) NULL,
CONSTRAINT pk_a PRIMARY KEY (ID),
CONSTRAINT fk_to_b
FOREIGN KEY (vj_users_preferences_id)
REFERENCES VJ_USER_PREFERENCES(ID)
);
CREATE TABLE B(
ID NUMBER(10) NOT NULL,
EXT_ID NUMBER(10) NOT NULL,
KEY VARCHAR2(1024) NOT NULL,
VALUE VARCHAR2(1024) NOT NULL,
CONSTRAINT PK_B PRIMARY KEY(ID)
);
For both tables I have entities and I want to map them #OneToOne.
class Entity A{
.......
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="pk_b", referencedColumnName = "id")
private B b;
}
Entity B is Audited and haven't got A field so connection is unidirectional. When I try to persist the A entity I got the error:
Caused By: org.hibernate.HibernateException: Could not determine type of dynamic map entity
This exception is being thrown from:
org.hibernate.tuple.entity.DynamicMapEntityTuplizer.BasicEntityNameResolver#resolveEntityName
Because the input is Map and it has not got: DynamicMapInstantiator.KEY in it.
Can somebody help me with this issue? I cannot figure out why Hibernate is creating that map without necessary value. Is there something wrong with my mapping?
It appeared that my UI form was receiving over 50 symbols, but database had:
EXT_ID NUMBER(10) NOT NULL
When I altered table to reflect UI possibilities (e.g. EXT_ID NUMBER(50) NOT NULL) then error was gone.
That exception, as per my understanding, is misleading in this kind of situation. I was expecting to see: SQLGrammarException of kind of it.
Hope this will help oneday.

Hibernate Creating a Map Collection Mapping

I want to create a Hibernate XML mapping for the following POJO Classes:
public class Topics {
private int topicId;
private Map<Integer,News> news;
//setters and getters
}
public class News {
private int newsId;
private Map<Integer,Topics> newstopics;
//setters and getters
}
My Tables are these:
CREATE TABLE topics (
topicid int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (topicid)
)
CREATE TABLE news (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
)
CREATE TABLE newstopics (
topicid int(11) NOT NULL,
newsid int(11) NOT NULL,
PRIMARY KEY (topicid,newsid),
CONSTRAINT FOREIGN KEY (topicid) REFERENCES topics (topicid) ON DELETE CASCADE,
CONSTRAINT FOREIGN KEY (newsid) REFERENCES news (id) ON DELETE CASCADE
)
I am trying something like this, but it is not working:
<class name="Topics" table="topics">
<id name="topicId" type="int" column="topicid"><generator class="native"/></id>
<map name="news" table="newstopics">
<key column="topicid"/>
<map-key column="newsid" type="int"/>
<many-to-many column="newsId" class="News" />
</map>
</class>
<class name="News" table="news">
<id name="newsId" type="int" column="id"><generator class="native"/></id>
<map name="newstopics" table="newstopics">
<key column="newsid" />
<map-key column="topicid" type="int"/>
<many-to-many column="topicId" class="Topics" />
</map>
</class>
Goal is to achieve a bidirectional mapping, meaning that when something changes in one map the contents of newstopics get updated too. I have tried multiple variations for the mapping of the maps but no luck. The most disturbing aspect ist that the hibernate genarated SELECTs and INSERTs from/to the newstopics table are looking for more that its 2 columns. For example INSERT INTO newstopics (topicid,newsid,id) VALUES ? ? ?

How to do cascade using hql query in hibernate

How to do cascade save or update using hql query in hibernate? also how can i use cascade update for some specific fields instead of updating all child table fields?
for example table User has
userName varchar(10)
Password varchar(10)
table UserAccessRights has
username varchar(10) FK of User table
password varchar(10) FK of User table
Authpassword varchar(10)
cascade update should happen only for username not for password. how can i acheive this?
You don't.
Since the cascade is a Hibernate configuration matter (i.e. HBM or annotations) the data must be returned to Java for processing of cascades. Doing UPDATE/DELETE row modifications in HQL happens entirely on the SQL server (and the SQL server does not understand JPA cascades, as JPA is a Java API not an SQL API or SQL standard).
You need to specify your cascade setting in your hbm files I suppose.
<set name="columnrecord" cascade="save-update" table="..."...>
<key>
<column name="COLUMN_NAME" not-null="true" />
</key>
<one-to-many class="..." />
</set>

Categories