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

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
}

Related

Prisma client generated type for create input has weird type requirement for related table field, how to get a working type?

Use case is simple:
users table
sessions table
Each user can be logged in multiple places therefore they can have multiple sessions -> one to many relationship. in SQL this isn't a big deal/problem, but the generated types available in #prisma/client create a weird type when it comes to the input models.
I'm using NestJS and need TS models based on classes that exist at runtime, so I can make use of decorators on keys for input validation and graphql usage.
I'm creating a model based off of the Prisma.SessionCreateInput coming from #prisma/client.
prisma schema:
model User {
id String #id #default(uuid())
...
sessions Session[]
}
model Session {
id String #id #default(uuid())
user User #relation(fields: [userId], references: [id])
userId String
}
The TS model:
import { Prisma } from '#prisma/client';
export class SessionModel implements Prisma.SessionCreateInput {
id?: string;
userId?: string;
user: Prisma.UserCreateNestedOneWithoutSessionsInput;
}
Now I'm defining the type for user explicitly based on what Prisma is telling me to, in my opinion I don't need any user data there when creating a session, merely the userId.
UserCreateNestedOneWithoutSessionsInput:
type Prisma.UserCreateNestedOneWithoutSessionsInput = {
create?: (Prisma.Without<Prisma.UserCreateWithoutSessionsInput, Prisma.UserUncheckedCreateWithoutSessionsInput> & Prisma.UserUncheckedCreateWithoutSessionsInput) | (Prisma.Without<...> & Prisma.UserCreateWithoutSessionsInput);
connectOrCreate?: Prisma.UserCreateOrConnectWithoutSessionsInput;
connect?: Prisma.UserWhereUniqueInput;
}
which seems some sort of meta type that I very much do not need?
How can I maintain type safety and have these derived TS classes to work with?

How to restore persistence properties that the domain model does not have

I have been thinking and reading about this for some time with not success.
I'm in the process of separating the db layer from the domain (I was using orm entities as domain entities).
To do it I have created simple mapper classes with methods to transform a persistence entity to a domain entity and viceversa.
The problem comes when a domain entity does not have all the persistence properties as they are useless for the bussiness logic (for example the user logo image url).
I map the user db result to its domain entity without saving the logo so when I try to convert it back to persistence I don't have a way to retrieve again the logo.
My question is, there is a pattern to solve this or a domain entity does have to always contain all the necessary info to be persisted even when that info is completely useless for the bussiness logic?
Code example:
// User persistence entity
class User {
name
is_active
account_id
logo
}
// User domain entity
class User {
name
isActive
account
}
// Mapper
class UserEntityMapper {
static toDomain(raw) {
return new User({
name: raw.name,
isActive: raw.is_active,
account: raw.account_id,
})
}
static toPersistence(User domain) {
return {
name: domain.name,
is_active: domain.isActive,
account_id: domain.account,
logo: // How tf can i get the logo here????
}
}
}

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").

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

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;
}

How to implemet a Many-to-Many relationship in Sequelizejs which also have relationship attributes?

So there are a lot of answers that explain how you model a Many-to-Many relationship in sequelizejs using hasMany() etc. But none of them has explained how and where do you store attributes which are created due to such an association, for eg: A customer can belong to or have many merchants and a merchant can have many customers, one such attribute of this relationship is a unique customer_id for a particular merchant-cutomer. Now where should this key(and any other detail) reside if we follow this: Stackoverflow answer
If you want additional attributes in your join table, you can define a model for the join table in sequelize, before you define the association, and then tell sequelize that it should use that model for joining, instead of creating a new one:
Customer = sequelize.define('customer', {})
Merchant = sequelize.define('merchant', {})
MerchantCustomers = sequelize.define('merchant_customers', {
customer_id: DataTypes.INTEGER
})
Merchant.belongsToMany(Customer, { through: MerchantCustomers })
Customer.belongsToMany(Merchant, { through: MerchantCustomers })
customer.addMerchant(merchant, { customer_id: 42 })
http://docs.sequelizejs.com/en/latest/docs/associations/#belongs-to-many-associations
To access the join table attributes:
c.getMerchants().then(function (merchants) {
merchants[0].merchant_customer.customer_id // Or perhaps merchant_customers, can't remember
});

Resources