Translate hibernate mapping anotations to hbm.xml file - java

I have such hibernate mapping annotation and I need to translate it to xml one.
#Entity
#Table(name = "nodes")
public class DefaultDiagramNode {
.....
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
#JoinColumn(name = "node_id", referencedColumnName = "id")
private Set<NodeProperty> properties;
}
Here is my sql table structure:
CREATE TABLE nodes (
id VARCHAR(255) NOT NULL,
logical_id VARCHAR(255) NOT NULL,
graphical_id VARCHAR(50) NOT NULL,
type VARCHAR(50) NOT NULL,
diagram_id BIGINT,
PRIMARY KEY (id),
FOREIGN KEY (diagram_id) REFERENCES diagrams (diagram_id)
);
CREATE TABLE node_properties (
property_id VARCHAR(255) NOT NULL,
name VARCHAR(50) NOT NULL,
value VARCHAR(255) NOT NULL,
type VARCHAR(50) NOT NULL,
node_id VARCHAR(255),
PRIMARY KEY (property_id),
FOREIGN KEY (node_id) REFERENCES nodes (id)
);
How can I do it?

Annotations really are a better choice for a new application. They are easier to read, remove the obtuse relationship between POJO and XML, and they less will result in less lines of code to maintain later. The annotations will also make it far easier to refactor your applications using IDEs such as Eclipse or IntelliJ.
Is there a pressing need to go back to XML? Otherwise, I'd avoid it.
Edit:
Ah, makes sense since you're using Thrift. Have have you tried looking at Swift? You may be able to just add these annotations to your Hibernate entity classes. https://github.com/facebook/swift/

Related

Spring Data JPA - #GeneratedValue annotation shows no affect

I have a problem regarding my implementation of a weak entity type. (Note, if that's important: I'm using H2 as my database)
Here is my datamodel:
I'm trying to implement Activity's concatenated primary key using two #ID annotated columns. Here is my activity class as well as its "owner"-class:
#Entity
public class Activity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Id
#ManyToOne
#JoinColumn
private UserGroup group;
...
}
#Entity
public class UserGroup {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
}
My expected outcome would be, that inside my activity table id is generated by default as identity and group_id is set depending on the corresponding group-join. Basically something like this:
create table activity
(
id bigint generated by default as identity,
begin_date_time timestamp(6),
end_date_time timestamp(6),
name varchar(255) not null,
note varchar(255),
group_id bigint not null,
room_id bigint,
primary key (group_id, id)
);
Instead, spring disregards my #GeneratedValue annotation and sets it to group_id, ignoring my actual activity.id column:
create table activity
(
id bigint not null,
begin_date_time timestamp(6),
end_date_time timestamp(6),
name varchar(255) not null,
note varchar(255),
group_id bigint generated by default as identity,
room_id bigint,
primary key (group_id, id)
);
This is a problem, as I plan on using Rest-Endpoints and Repositories to run CRUD operations using HTTP-requests. Having an ID-counter that increments and gets new IDs for one table only seems unnecessary and dirty.
Can somebody explain to me why this is happening? Can I manually annotate group_id as a manually assigned field as a quick workaround?
Cheers!
What you are looking for is a composite key, which you can create with either #IdClass or with #Embeddable and #EmbeddedId. The catch is, however, that neither of these approaches will work with a #GeneratedId.
If you think about it, there's no need to have a composite key where one of the parts is autogenerated. Just have one Id on your entity that's auto generated, and if you want, create an index across (group_id, id).

Schema-validation: missing table [...] error message using flyway for a SQL code generated by Hibernate

I've been trying to deal with some problems regarding Flyway. My situation is the following: I have two Java classes, which I'd like to migrate as two schemas. Let's name them Table and CustomTable. My java classes look like:
#Entity
public class xtable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
//getters, setters, constructors
#Entity
public class CustomTable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String a;
private String b;
private String c;
//getters, setters, constructors
My application.properties:
spring.flyway.url=${env.var1}
spring.flyway.user=${env.var2}
spring.flyway.password=${env.var3}
spring.jpa.hibernate.ddl-auto=validate
//If I use create-drop, hibernate creates it, but after that the validation fails
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
spring.logging.level.org.hibernate.SQL=debug
spring.jpa.show-sql=true
hibernate.temp.use_jdbc_metadata_defaults=true
spring.flyway.enabled=true
My build.gradle:
plugins {
id "org.flywaydb.flyway" version "5.2.4"
}
dependencies {
implementation 'org.flywaydb:flyway-core'
}
The situation is so weird, because it does not even work with the auto-generated SQL code, which I let the program create without flyway.
It looks like this:
create table custom_table (
id bigint not null,
a varchar(255),
b varchar(255),
c varchar(255),
xtable_id bigint,
primary key (id)
)
engine = InnoDB;
create table xtable (
id bigint not null,
name varchar(255),
xtable_id bigint,
primary key (id)
)
engine = InnoDB;
alter table custom_table
add constraint FKep6vooglihwraille12muox9 foreign key (xtable_id) references xtable (id);
alter table xtable
add constraint FK426q765pr4gv5wux6jaktafqk foreign key (custom_table_id) references custom_table (id);
I also don't understand why Hibernate creates one-one foreign key into each class, but the bigger problem is that I still get the error message
Schema-validation: missing table [custom_table]
I tried renaming custom_table to customtable (and also renaming the class in Java), but the error message was the same.
Have you ever met the same problem? Have you got any suggestions? I've been working on this problem for - at least - 2 days.
I looked for relevant - or seemingly identical - topics here, but I couldn't find a good solution.
Thank you.
Finally I got the problem. The problem was with inserting multiple foreign keys. (So these two lines):
alter table custom_table
add constraint FKep6vooglihwraille12muox9 foreign key (xtable_id) references xtable (id);
alter table xtable
add constraint FK426q765pr4gv5wux6jaktafqk foreign key (custom_table_id) references custom_table (id);
I couldn't figure out, though, the reason why Flyway couldn't handle this, but when I recreated the whole structure with the two tables and another one containing the proper ID's, doing exactly the same thing in the whole project, it worked.

Mapping Entity objects by database schema in intelij generates bad annotations and relations

I have followin sql:
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`power_id` int(11) NOT NULL
)
ALTER TABLE `user`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `power_id` (`power_id`),
ALTER TABLE `user`
ADD CONSTRAINT `FK_user_power` FOREIGN KEY (`power_id`) REFERENCES `power` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
CREATE TABLE `power` (
`id` int(11) NOT NULL,
`updated_date` date NOT NULL
)
( its hand typed )
However when i do view Persistence -> Generate Persistance Mapping -> By Database Schema It generated this in User entity class:
private PowerEntity powerByPowerId;
#ManyToOne
#JoinColumn(name = "power_id", referencedColumnName = "id", nullable = false)
public PowerEntity getPowerByPowerId() {
return powerByPowerId;
}
which is clearly 1:n relation ( e.g multiple users have one power ) while sql says about 1:1 relation.
NOw i am unsure if my sql is wrong or intelij generated wrong relatios.
How to deal with it? My database schema is not small and so far i have noticed only this mistake, however i am not sure if its my fault or intelij's mapping is producing wrong entity tables ( which would mean i could find another badly generated entity ).
Thanks for help.

Hibernate not preserving referential integrity

In hibernate I have created a one-to-many relationship between user and roles.
More then one user can be associated with a role, but a user can be associated with just one role.
In User class, I have
#ManyToOne
#JoinColumn(name = "role_id")
private Role role_id;
In Role Class, I have
#OneToMany(mappedBy="role_id", fetch=FetchType.LAZY)
private Collection<User> userList = new ArrayList<User>();
If I am saving a new user as :
{
"userName" : "Michael",
"role_id" : {
"id" : 8
}
}
It saves user even when role table has no role with id as 8( and no entry is done in role table).
I want that I should get a referential integrity error whenever I am saving a user with a non existent role.
What should I change?
My Users table is created as:
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
`mobile` varchar(255) DEFAULT NULL,
`username` varchar(255) NOT NULL,
`role_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_abcdef` (`role_id`),
CONSTRAINT `FK_abcdef` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Do you have FK constraint in your tables in the database? Maybe this if you use mySql can help you. Or alternatively you can set the restriction in your database by your own.
In your #OneToMany annotation you probably need to add targetEntity = User.class. That is because of the following reasons:
java generics use type erasure, which means that in the generated bytecode, your userList is of type Collection, not of type Collection<User>. So, hibernate has no clue what the target entity is, unless you explicitly tell it.
Hibernate generally likes to follow a silent error / hidden error approach, which means that it silently ignores problems the moment they happen (as for example the moment where it has no clue what type your collection elements are) and to fail later, when the cause of the problem is not very clear anymore. (As for example when you execute a query which should fail, and it doesn't, or you execute a query which should fetch something, and it fetches nothing.)
As of java 9, the compiler does actually store information about the actual type arguments used when creating generic fields within the generated .class files, and it is possible to discover that information using reflection, but I am not aware of hibernate having been updated to check this information.

Problem with JPA Mapping One-to-Many with jointable

I have a JPA Mapping question to do.
We have a One-To-Many relationship between two entities (Sale and Pig). Classes follow at the final of this message to ilustrate.
'Sale' is a event on a 'Pig', like many others in the system ('Inspection' is another example).
However, 'Sale' is the only event who has One-To-Many relationship with 'Pig', the others has One-to-One.
So, to map all events of a 'Pig' we use a 'PigEvent' entity.
We save(insert) a 'PigEvent' object at the same time the user inserts a 'Pig' in the system.
We want to use this entity ('PigEvent') like the 'jointable' of Sale.getPigs() mapping.
But doing that, some problem occurs:
- when a new 'Sale' is inserted, hibernate try to insert new 'PigEvent' for every 'Pig' in the 'Sale'
(this generates a duplicate PK exception, because PigEvent already exists)
- when a new 'Sale' is deleted, hibernate deletes 'PigEvent' for every 'Pig' in the 'Sale'
(doing this we loose the others Events relationship data)
We understand that this is the normal behaviour of this kind of mapping (One-to-Many with jointable).
We want to know how configurate JPA/Hibernate to just load Sale.getPigs() (in SELECT´s),
but in INSERT, UPDATE, DELETE operations in 'Sale' don´t action at all in that mapping (Sale.pigs()).
We use Hibernate 3.6.2.
Thanks in advance.
#Entity
public class Pig extends Persistente implements Serializable {}
#Entity
public class PigEvent extends Persistente {
#OneToOne
#JoinColumn(name="idpig")
private Pig pig;
#OneToOne
#JoinColumn(name="idapproval")
private Inspection approval
#OneToOne
#JoinColumn(name="idsale")
private Sale sale;
}
#Entity
public class Inspection extends Persistente{
#OneToOne
#JoinColumn(name="idSuino")
private Pig pig;
}
#Entity
public class Sale extends Persistente{
#MOneToMany
#JoinTable(name="e33PigEvent",uniqueConstraints=#UniqueConstraint(columnNames="idpig"),
joinColumns={#JoinColumn(name="idsale",insertable=false,updatable=false)},
inverseJoinColumns={#JoinColumn(name="idpig",insertable=false,updatable=false)})
public Set<Pig> getPigs() {}
}
Table Structure:
CREATE TABLE `e33Pig` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
CREATE TABLE `e33PigEvent` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`idPig` int(11) NOT NULL,
`idInspection` int(11) DEFAULT NULL,
`idSale` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idPig` (`idPig`),
CONSTRAINT `fk_e33eventossuino_e33aprovacao1` FOREIGN KEY (`idInspection`) REFERENCES `e33Inspection` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `fk_e33eventossuino_e33suino1` FOREIGN KEY (`idPig`) REFERENCES `e33Pig` (`id`),
CONSTRAINT `fk_e33eventossuino_e33venda1` FOREIGN KEY (`idSale`) REFERENCES `e33Sale` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
);
CREATE TABLE `e33Sale` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE e33Inspection (
`id` int(11) NOT NULL AUTO_INCREMENT,
`idsuino` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_e33Inspection_e33suino1` FOREIGN KEY (`idPig`) REFERENCES `e33Pig` (`id`)
) ;
You can't use the same table (e33PigEvent) to map an entity (PigEvent) and an association (the OneToMany association). If the table is mapped to an entity, then you don't have a OneToMany association between Sale and Pig anymore: you have a OneToMany between Sale and PigEvent, mapped by a foreign key in e33PigEvent, and a OneToOne between PigEvent and Pig, also mapped by a foreign key in e33PigEvent.
If you map a OneToMany using a JoinTable, then Hibernate handles insertions and deletions in this table itself, each time you add or remove Pigs from the collection. Since you have additional columns in the join table, you need to create PigEvent instances yourself, and add these instances to the collection of events of the sale.

Categories

Resources