How to create an entity's relationship to itself? For example, hierarchical folders - jhipster

I'm trying to create a hierarchical folder structure. Here's my Folder entity:
$ yo jhipster:entity Folder
The entity Folder is being created.
Generating field #1
? Do you want to add a field to your entity? Yes
? What is the name of your field? name
? What is the type of your field? String
? Do you want to add validation rules to your field? No
=================Folder=================
name (String)
Generating field #2
? Do you want to add a field to your entity? Yes
? What is the name of your field? parentId
? What is the type of your field? Long
? Do you want to add validation rules to your field? No
=================Folder=================
name (String)
parentId (Long)
Generating field #3
? Do you want to add a field to your entity? No
=================Folder=================
name (String)
parentId (Long)
I'm trying to map out just what I need to provide jhipster's entity generator to make it work. This is what I have so far...
Generating relationships with other entities
? Do you want to add a relationship to another entity? Yes
? What is the name of the other entity? Folder
? What is the name of the relationship? parent
? What is the type of the relationship? one-to-many
? What is the name of this relationship in the other entity? child
Am I on the right track? How do I create the child many-to-one relationship? I get a warning if I try to create it with the Folder entity. There's no way to generate it afterwards.

You can use https://jhipster.github.io/jdl-studio/ for writing as jdl for creating entities.
Please visit https://jhipster.github.io/jhipster-uml/#jdl for more information.
This is a sample JDL that has relationship to itself :
entity RankProperties {
rank Integer required,
minExp Integer required,
maxExp Integer required,
maxStamina Integer required,
maxAlly Integer required,
maxTeam Integer required
}
enum TaskMode {
NO_CONTINUE_STAGE_COUNT,
STAGE_COUNT,
STAGE_ID
}
entity Task {
taskMode TaskMode required,
value Integer required
}
relationship ManyToOne {
Task{parent} to Task
}
dto all with mapstruct
service all with serviceClass

I recommend to use jdl model.
entity A { property1 String }
relationship OneToMany {
A{sons} to A{parent}
}
The model generates a Entity java class like (some annotations ignored):
class A {
#OneToMany(mappedBy="parent")
private Set<A> sons = new HashSet<>();
#ManyToOne
private A parent;
}

Related

Creating entity relationship using a jdl in jhipster

I have the below JDL that I am using to create the jhipster application.
entity AuthClient(auth_client) {
msisdn String required maxlength(255),
email String required unique maxlength(255),
password String required maxlength(255),
lastLogin Instant,
createdAt Instant required,
createdBy Integer,
updatedAt Instant,
updatedBy Integer,
isDeleted Boolean required,
deletedAt Instant,
deletedBy Integer
}
entity AuthToken(auth_token) {
token String required maxlength(255),
appId Integer required,
appVersionName String maxlength(255),
clientId Integer required,
}
entity ClientProfile(client_profile) {
fName String required maxlength(255),
mName String maxlength(255),
lName String required maxlength(255),
gender Integer,
clientId Integer required
}
// Relations
relationship OneToMany {
AuthClient{AuthToken(clientId)} to AuthToken{AuthClient}
}
relationship OneToOne{
ClientProfile{AuthClient} to AuthClient{ClientProfile(clientId)},
}
// Options
service * with serviceClass
paginate * with pagination
dto * with mapstruct
filter *
However, instead of using the variable clientId as the foreign key it creates another field in the database.
I need to use the clientId as the foreign key in this application and not the generated new field Auth Client
Defining a clientId field as you did has no impact on the relationship, these are two separate things.
When you define a relationship, a field is automatically created in the entity and its type is of the related class: it's a reference to an object in the java entity and a foreign key column in the database table.
By default, the foreign key column will be named as auth_client_id and the field will be named as authClient. However, the JDL syntax for relationships lets you configure the relationship name and so modify the generated names.
So, remove all the clientId fields and modify your relationships definitions as follows:
// Relations
relationship OneToMany {
AuthClient to AuthToken{client}
}
relationship OneToOne{
ClientProfile{client} to AuthClient
}
This way you get the foreign key column named as client_id and the field named as client.
You can then define also which field of the related entity will be used for display in the generated UI.
There is more to learn about relationships in the doc: https://www.jhipster.tech/jdl/relationships

Jhipster - setting up many to many relationship for user-entities

Want to create entity called Friendship and want to leverage the User entity that's part of Jhipster,
But I keep getting this invalid-relationship error (full error below).
User has friends (user entities) and vice-versa
entity UserExtended {
}
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}
}
entity Post {
owner UserExtended,
content String,
dateCreated LocalDate
}
entity Like {
likedBy UserExtended,
post Post,
dateCreated LocalDate
}
entity Comment {
postedBy UserExtended,
post Post,
dateCreated LocalDate
}
relationship OneToMany {
UserExtended{post} to Post{user}
}
relationship OneToMany {
Like{post} to Post{like}
}
relationship OneToMany {
Comment{post} to Post{comment}
}
Error:
Error: Can't add invalid relationship. Error: In the Many-to-One relationship from UserExtended to UserExtended, only unidirectionality is supported, you should either create a bidirectional One-to-Many relationship or remove the injected field in the destination entity instead.
Error while parsing applications and entities from the JDL Error: Can't add invalid relationship. Error: In the Many-to-One relationship from UserExtended to UserExtended, only unidirectionality is supported, you should either create a bidirectional One-to-Many relationship or remove the injected field in the destination entity instead.
Error: Can't add invalid relationship. Error: In the Many-to-One relationship from UserExtended to UserExtended, only unidirectionality is supported, you should either create a bidirectional One-to-Many relationship or remove the injected field in the destination entity instead.
You have several problems in your JDL. For example, you should not mix relationships and entities like this:
entity Post {
owner UserExtended, // <-- This is a problem
content String,
dateCreated LocalDate
}
If I have understood your requirements correctly you want to design a kind of blog and let users form friendships. JDL will not let you add relationships starting from the core entity User so you have created a UserExtended and will possibly store some extra information there.
Remember that you can design multiple relationships inside one relationship block. In fact I think it is a good practice, makes the whole JDL a bit more readable.
This should do what you need:
entity UserExtended
entity Friend {
status Boolean
modified LocalDate
created LocalDate
}
entity Post {
content String
dateCreated LocalDate
}
entity Like {
dateCreated LocalDate
}
entity Comment {
dateCreated LocalDate
}
relationship OneToOne {
UserExtended{user(login)} to User
}
relationship ManyToOne {
Post{owner} to UserExtended
Comment{postedBy} to UserExtended
Like{likedBy} to UserExtended
Friend{user} to UserExtended
}
relationship OneToMany {
UserExtended{friends} to Friend
Post{likes} to Like
Post{comments} to Comment
}
The only tricky part here is the many-to-many between two users in a relationship called Friend. You need to store some extra information about the friendship (status, modified, created) so we had to split this many-to-many into a one-to-many plus a many-to-one using the Friend entity as a join table with extra fields.
I did not change your naming scheme, which could probably be improved.
Remember to check the official documentation and optionally use JHipster Online for JDL storage and validation.
Try renaming
relationship OneToOne {
UserExtended{user(login)} to User
}
to
relationship OneToOne {
UserExtended{somethingElse(login)} to User
}

Force database tablename for collection relationship in Sails

In a sails project, considering a model User and a model Role, with a relationship between User and Role :
// `User.js
module.exports = {
attributes: {
...
roles: {
collection: 'role',
dominant: true
},
...
}
}
For the the database representation, sails/waterline will create following tables :
table user,
table role,
table like user_roles__role_roles_role to represent the collection
I know we can force the name for the models USER and ROLE
(with the property 'tablename' : http://sailsjs.com/documentation/concepts/models-and-orm/attributes).
But how can we force the name the relationship table ? (Especially this name is quite long and tends to exceed limit).
Assuming this is a two-way relationship, and the Role model has a users collection, Sails will expect a table named role_users__user_roles, which has the role id first, user id second.
Your example table name would require User to be dominant and would require the Role model to have an attribute named roles_role that is a User collection.
To create your own join table, you can use the through association method and add a new model that represents the relationship, perhaps UsersRoles, and specify the tableName in that model definition.
Examples of the through association:
sails
docs
similar question
gist from comments in that question

proper way to reference documents with Mongoose

I see in all examples the suffix "_id" on a field referencing to another document.
Example:
record: {
_id : ObjectId("57f2fb5d1c6c3b0de45b170e",
artist_id: "prince" )
}
artist: {
_id: "prince"
}
Being that my artist mongo Schema has the "unique" attribute on the name field.
Is it Ok to things like below ?
record: {
_id : ObjectId("57f2fb5d1c6c3b0de45b170e",
artist: "prince" )
}
artist: {
_id : ObjectId(6eygdqzd5d1c6c3b0de45b1s0r",
name: "prince"
}
Or should you always reference directly the Id like in the first example?
if you visualize your problem in RDBMS world, there too to establish a foreign key constraint the field should be primary key in the referenced table and the same rule applies here.
now in your artist document though each document is going to contain a unique artist name but the name field itself is not key (primary key) but the ID is.
hence you have to establish the reference using the _id field.
what you can do is for ease if you want rather than relying on the mongodb generated ID field you can probably use name as the _id.

Droidparts: how to get to autocreated column names in m2m table?

community.
I am just start to use droidparts.
As I got it is cool library. But it has poor documentation, and no comments in code itself.
I am interested in getting elegant approach to use it.
Well suppose, i've created tables items, users, items2users as many-to-many concept.
Tables items and users are trivial. Table items2users is
#Table(name="items2users")
public class ItemsToUsers extends Entity {
#Column
public Item item;
#Column
public User user;
}
So if I need to get answer if my User has Item I do something like that in UserManager class:
public boolean hasItem(Item item) {
Select<ItemsToUsers> select = select().columns(ID).where({HERE_I_NEED_COLUMN_NAME}, Is.EQUAL, user.id);
}
Droidparts made table with fields 'item_id' and 'user_id'. As I understand HERE_I_NEED_FIELD_NAME must be 'user_id'. As I realize it is automatic naming model for this situation?
Well is there some elegant technique to achive this names or I should construct them manually getting 'user' and '_' and 'id'?
By default the column name will be field name + _id, e.g. item_id & user_id in your case. That can be altered through annotation, e.g. #Column(name="some_other_name").

Resources