JHipster many to many relationship with extra field - jhipster

I've generated a ManyToMany relationship between two entities but I need to add a extra field in the join table
#ManyToMany
#JoinTable(name = "cliente_modulo",
joinColumns = #JoinColumn(name = "cliente_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "modulo_id", referencedColumnName = "id"))
private Set<Modulo> modulos = new HashSet<>();
In this way is added a new table in database but is not created a new entity.
How to generate a ManyToMany relationship that adds a entity with extra field?

Instead of a ManyToMany relation you can setup a OneToMany between Cliente and ClienteModulo and a ManyToOne between ClienteModulo and Modulo.
This should generate the join table as before but also the model entity and everything else you need.
Something like:
entity Cliente{}
entity ClienteModulo{}
entity Modulo{}
relationship OneToMany {
Cliente{clienteModulos} to ClienteModulo{cliente}
}
relationship ManyToOne {
ClienteModulo{modulo} to Modulo{clienteModulos}
}
Add the properties you need to ClienteModulo.

Related

Jhipster User friend self relationship

I want to create a "friend" relationship between User using an entity "Friend".
I try this, but it isn't work.
entity Friend {
status Boolean,
modified LocalDate,
created LocalDate
}
relationship ManyToMany {
Friend{user(login)} to User,
User to Friend{user(login)}
}
How i can do that ?
Thanks
You cannot create relationship with User entity in JDL
A workaround is to create another entity and use a one-to-one relationship like this
entity Friend {
status Boolean,
modified LocalDate,
created LocalDate
}
entity UserExtended {
...
}
relationship OneToOne {
UserExtended to User
}
relationship ManyToMany {
Friend{userExtended(login)} to UserExtended,
UserExtended to Friend{userExtended(login)}
}
You may want to consider creating the relationship with the User directly in the generated code.
Found it :
entity UserExtra {
.....
}
entity Friend{
status Boolean,
modified LocalDate,
created LocalDate
}
relationship OneToOne {
UserExtended{user(login)} to User
}
relationship OneToMany {
UserExtended{friends} to Friend{user}
}
relationship ManyToOne {
UserExtended{friend} to UserExtended{users}
}

Why jhipster:import-jdl is giving me an IllegalAssociationException?

I have this UML:
entity Profile {
creationDate Instant required
bio String maxlength(7500)
}
entity Grupo {
creationDate Instant required
groupname String minlength(2) maxlength(100) required
image ImageBlob
isActive Boolean
}
// RELATIONSHIPS:
relationship OneToOne {
Profile{grupo} to Grupo{profile}
}
relationship OneToMany {
User{grupo} to Grupo{user(id) required}
}
// DTO for all
dto * with mapstruct
// Set pagination options
paginate all with pagination
// Set service options to all except few
service all with serviceImpl
and when I run it with yo jhipster:import-jdl it gives the following error:
IllegalAssociationException: Relationships from User entity is not supported in the declaration between User and Grupo.
Error jhipster:import-jdl ./src/main/scripts/raro.jh
Is it NOT allowed to have a OneToMany relationship with the User Entity? The thing is that OneToOne relationships works fine.
Because when I change the relationship to ManyToOne, it works
entity Profile {
creationDate Instant required
bio String maxlength(7500)
}
entity Groups {
creationDate Instant required
groupname String minlength(2) maxlength(100) required
image ImageBlob
isActive Boolean
}
// RELATIONSHIPS:
relationship OneToOne {
Profile{groups(groupname)} to Groups{profile}
}
// relationship OneToMany {
// User{groups} to Groups{user(id) required}
// }
relationship ManyToOne {
Groups{user(id) required} to User{groups}
}
// DTO for all
dto * with mapstruct
// Set pagination options
paginate all with pagination
// Set service options to all except few
service all with serviceImpl
Why? Am I doing something worng in the first example?
Thanks
JHipster does not allow OneToMany relationships to the user by default. If you need this, you will have to manually change the code.
Please note that the User entity, which is handled by JHipster, is specific. You can do:
many-to-one relationships to this entity (a Car can have a many-to-one relationship to a User)
many-to-many and one-to-one relationships to the User entity, but the other entity must be the owner of the relationship (a Team can have a many-to-many relationship to User, but only the team can add/remove users, and a user cannot add/remove a team)
https://www.jhipster.tech/managing-relationships/

How to relate two entities in Jhipster JDL?

Let's say you have a Jhipster app that has a Profile and needs to register which Profiles follows other profiles with 2 attributes: one for the user that is following (user Profile) and another for the followed user (followed Profile). Something like:
entity Profile {
creationDate Instant required
}
entity Follows {
creationDate Instant
}
relationship OneToMany {
Profile{follows(user)} to Follows{profile(id)}
Profile{follows(followed)} to Follows{profile(id)}
}
The problem with this is that the Follows.java has 2 identical atributes even when the names are different follows(user) & follows(followed):
#ManyToOne
private Profile profile;
... instead of...
#ManyToOne
private Profile user;
#ManyToOne
private Profile followed;
Thanks.
You are using the same relationship name for both relationships, but each relationship name needs to be different or else the fields conflict.
relationship (OneToMany | ManyToOne | OneToOne | ManyToMany) {
<from entity>[{<relationship name>[(<display field>)]}] to <to entity>[{<relationship name>[(<display field>)]}]
}
JDL Relationship Declaration Docs
In the case of your JDL sample, I changed the display field from user/followed to id as those fields do not exist on the entity. The important change is that the relationship names are unique.
relationship OneToMany {
Profile{followed(id)} to Follows{followed(id)}
Profile{following(id)} to Follows{following(id)}
}
entity Profile {
creationDate Instant required
}
entity Follows {
creationDate Instant
}
relationship ManyToOne{
Follows{user} to Profile
Follows{followed} to Profile
}
Supposing you want relation between Rooms and Patient
You can have these entities
entity NmsPatient {
photo ImageBlob
}
entity NmsRoom {
code String required,
name String required
}
entity NmsPatientRoom {
begin ZonedDateTime,
end ZonedDateTime
}
And then
relationship ManyToOne {
NmsPatientRoom{patient} to NmsPatient,
NmsPatientRoom{room} to NmsRoom
}

OpenXava populating Collection from database

I have a problem populating a detail view from the database.
application.xml snippet:
<module name="ModuleB">
<model name="B"/>
<view name="ViewB"/>
...
<mode-controller name="DetailOnly"/>
</module>
I have three entity classes:
#Entity
#Table(name="A")
class A {
#OneToMany(mappedBy = "a")
#ListProperties("col1")
#CollectionView("cs")
private Collection<C> cs;//+getter/setters
}
#Entity
#Table(name="A")
#View(name = "ViewB", ...)
class B {
#OneToMany(mappedBy = "a")
#ListProperties(...)
#CollectionView("ViewC")
private Collection<C> cs;//+getter/setters
}
#Entity
#Table(name="C")
#View(name = "ViewC", ...)
class C {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "a_id")
private A a;
}
I want to read an existing B instance from the database by clicking on a link, then editing/modify it.
When I set the model object of the view with getView().setModel() or even using getView().findObject(), on the screen everything looks good, the collection shows its proper content.
On the other hand when i try to save it back, in the save action the getView().getEntity().getCs() collection is null.
What do I have to do to make the view being correspond to the entity behind?
I am using OpenXava 5.0.1, java 1.7
Important note: I am not allowed to change OpenXava version, since it is a legacy project.
My editing (20170126)
I've made a new class to avoid a reference problem:
#Entity
#Table(name="C")
#View(name = "ViewC", ...)
class D {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "a_id")
private B a;
}
and modified the class B accordingly:
#Entity
#Table(name="A")
#View(name = "ViewB", ...)
class B {
#OneToMany(mappedBy = "a")
#ListProperties(...)
#CollectionView("ViewC")
private Collection<D> cs;//+getter/setters
}
But the result is the same: The records of the subview (Collection ViewC) are loaded from the DB,
and shown on the screen correctly, but I get an error message if I want to edit the Collection ViewC
( eg: add a new entry ):
"Impossible to execute Save action: Impossible to create: an object with that key already exists"
+ As before: in the save action the getView().getEntity().getCs() collection is null
OpenXava uses JPQL to obtain collection data instead of just calling the collection getter, this is for allowing filtering and ordering. The problem here is that the query sentence generated by OpenXava gets the data but the getter of the JPA entity not. Surely JPA/Hibernate is not very happy with a mappedyBy to a reference to another type. That is you write:
class B {
#OneToMany(mappedBy = "a")
#ListProperties(...)
#CollectionView("ViewC")
private Collection<C> cs;//+getter/setters
}
Where a is a reference to A, not to B.
Given that A and B map the same table, why not to use just one entity?

Populating field from enum table

I have the following tables
Entity
id,name,categoryid
21,"Blah",1
EntityCategory(Enum table)
id, name
1,"New Blahs"
I have a FK relationship between Entities->categoryid and EntityCategories->id
I have generated SubSonic classes for both as well a corresponding Model object for Entity
class Entity{ID,Name,CategoryName}
I am trying to return the Model.Entity type with category name filled in i.e.
public Entity GetEntityByName(string name){
return new
Select(
Entity.IdColumn,
Entity.NameColumn,
EntityCategory.NameColumn)
.From(Entity.Schema)
.InnerJoin(Tables.EntityCategory)
.Where(Entity.NameColumn).IsEqualTo(name)
.ExecuteSingle<Model.Entity>();
Needless to say this is not working. I actually get a Model.Entity with the Entity.Name set to the EntityCategoryName.
If you use SubSonic 3.0 you can do this with projection:
var result = from e in db.Entities
where e.ID=1
select new Entity{
ID=e.ID,
name=e.Name,
CategoryName=(CategoryName)e.CategoryID
}
With SubSonic 2.x, I'd say to make it easy on yourself and extend the partial class with a readonly enum:
public partial class Entity{
public CategoryName{
return (CategoryName)this.CategoryID;
}
}

Resources