Can i create multiple schema in prisma for each model? - schema

This is a default structure of prisma schema...
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int #id #default(autoincrement())
username String #unique #db.VarChar(255)
role UserRole #default(admin)
posts Post[]
}
model Post {
id Int #id #default(autoincrement())
title String
post String #db.VarChar(500)
created_at DateTime #default(now())
updated_at DateTime #updatedAt
user_id Int
user User #relation(fields: [user_id], references: [id])
}
//custom enums
enum UserRole {
client
admin
}
I want to create multiple schema for each models. User schema for user model, Post schema for post model. Like we use models in mongoose. Is it possible in Prisma ORM?

Since Prisma hasn't introduced any solution for this matter yet, used this awesome package Prismix and solved the issue. Thanks, everyone!

Prisma multiSchema is now supported as a preview feature.
See here https://www.prisma.io/docs/guides/database/multi-schema
It was introduced in version 4.3.0 https://github.com/prisma/prisma/issues/1122#issuecomment-1231773471
As the docs say you would add the preview feature...
generator client {
provider = "prisma-client-js"
previewFeatures = ["multiSchema"]
}
Then in your datasource you note the schemas...
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
schemas = ["User", "Post"]
}
And finally in each model you add the ##schema attribute...
model User {
id Int #id #default(autoincrement())
username String #unique #db.VarChar(255)
role UserRole #default(admin)
posts Post[]
##schema("User")
}
model Post {
id Int #id #default(autoincrement())
title String
post String #db.VarChar(500)
created_at DateTime #default(now())
updated_at DateTime #updatedAt
user_id Int
user User #relation(fields: [user_id], references: [id])
##schema("Post")
}
Note:
It might not be possible to do cross schema foreign keys. I saw it mentioned somewhere, but I can't find it now.

Yes, We Can create multiple schemas for each model.

Related

How can we assign a field of user table say id that is primary key, to another table as a primary key? using hibernate

See I dont want any mapping but what I want is just a simple thing that is....
I have two Entity
Tasks(taskid,taskname.....,userId)
User_Credentials(userId,password)
So What I want is userId of User Credentials used as a foreign key in Task table.
So when I fire an api to save the task I have to also pass the all details of user Credentials That I dont want.
{
"taskName": "Test",
"taskStatus": "Open",
"taskDueDate": "2022-04-15",
"taskCreatedDate": "2022-04-10",
"taskDescription": "Demo",
"taskPriority": "High",
"isTaskActive": "Yes",
"userCredentials":{
"associateId":"108",
"password":"something#9122"
}
}
What I want is
{
"taskName": "Test",
"taskStatus": "Open",
"taskDueDate": "2022-04-15",
"taskCreatedDate": "2022-04-10",
"taskDescription": "Demo",
"taskPriority": "High",
"isTaskActive": "Yes",
"userCredentials":"108"
}
That I want to post and if userCredentials id 108 is not in User Credentials Table so it pop up an error and if it is there it will save just like a foreign key concept.
So please tell me ho to do that.
You can use ElementCollection to achieve this.
In Tasks entity
#Id
#Column(name = "task_id")
private Integer id;
#ElementCollection
#CollectionTable(name = "task_user", joinColumns = #JoinColumn(name = "task_id", nullable = false))
#Column(name = "user_id", nullable = false)
private List<Integer> userCredentials;
In UserCredentials entity
#Id
#Column(name = "user_id")
private Integer id;
UserCredentials is an independent entity with no mapping with Tasks. You will now be able to pass UserCredentials like this userCredentials: [108] in the Tasks.
Add the following in your application.yml to generate the create.sql script with ddl commands for all the entities. ddl-auto: validate will restrict hibernate from creating the tables on its own.
spring:
jpa:
hibernate:
ddl-auto: validate
properties:
javax:
persistence:
schema-generation:
create-source: metadata
scripts:
action: create
create-target: create.sql
generate-ddl: true
The following is the ddl command to add foreign key constraints for tables user_credentials and tasks. Execute it alongwith the create.sql in any DB client.
CREATE TABLE "task_user"
( "user_id" integer ,
"task_id" integer,
PRIMARY KEY ("user_id","task_id"),
CONSTRAINT user_id_fkey
FOREIGN KEY ("user_id") REFERENCES "user_credentials" ("user_id"),
CONSTRAINT task_id_fkey
FOREIGN KEY ("task_id") REFERENCES "tasks" ("task_id")
);
Note: The create.sql already has a task_user create command but it needs to be replaced with the above command.

Entity Framework Core wrong format date in database but read correct

I'm working on my project with ASP.NET Core 3.1 and Entity Framework Core. I have a table with a column of Date datatype:
[Column(TypeName = "Date")]
[Required]
public DateTime Date { get; set; }
Recently when I insert data in this table, date is inserted like below:
It is marvelous that when I read data from this table to show in calendar plugin, date is correct format:
This is my code for save data in database:
var dtDate = Convert.ToDateTime(date);
_db.ImPossibleReserveDates.Add(new ImPossibleReserveDate
{
Date = dtDate.Date,
InsertTime = DateTime.Now,
IsRemoved = false
});
And this code for read data:
var list = _db.ImPossibleReserveDates.Where(x => !x.IsRemoved).Select(x => new
{
date = x.Date.ToString("yyyy-MM-dd"),
TITLE = "تعطیل"
});
No matter in server or local!
Why did this happen?
check your converted date in server before save it
its seem two convert in your date

Can't make two 1:1 relations in one model in Prisma. Ambiguous relation detected

I'm trying to make two 1:1 relations in one model in Prisma ORM, but got following error:
Error validating model "Person": Ambiguous relation detected. The fields placeOfBirth and placeOfDeath in model Person both refer to Place. Please provide different relation names for them by adding #relation(<name>).
My prisma schema:
model Place {
id Int #id #default(autoincrement())
name String
persons Person[]
}
model Person {
id Int #id #default(autoincrement())
name String
placeOfBirthId Int
placeOfDeathId Int
👉 placeOfBirth Place #relation(fields: [placeOfBirthId], references: [id])
placeOfDeath Place #relation(fields: [placeOfDeathId], references: [id])
}
Totally don't get it.
You have to add a name field to placeOfBirth and placeOfDeath. Then use these names to reference both of them in the Place model.
model Place {
id Int #id #default(autoincrement())
name String
Births Person[] #relation("Births")
Deaths Person[] #relation("Deaths")
}
model Person {
id Int #id #default(autoincrement())
name String
placeOfBirthId Int
placeOfDeathId Int
placeOfBirth Place #relation("Births", fields: [placeOfBirthId], references: [id])
placeOfDeath Place #relation("Deaths", fields: [placeOfDeathId], references: [id])
}

GORM Domain Mapping Issue

I've got a bit of a complicated domain model I'm trying to implement and I'm having some trouble. (On top of that, I'm quite new to all this!)
I have a User domain which has multiple roles and multiple tests. The Role domain works great. The Test domain is a bit more compilciated though because it requires two foreign keys instead of just 1 like in the Role domain. The first foreign key is the user_id and the second is a uni_id (university ID).
The User domain model contains the following
class User {
static hasMany = [roles:Role, tests:Test]
Integer userId
...
static mapping = {
table 'user_data'
id generator: 'assigned', name: 'userId', type: 'long'
userId column: 'user_id'
version false
roles joinTable:[name:'user_role', key:'user_id']
tests joinTable:[name:'user_test', key:'user_id'] // Here is where I run into trouble
}
static constraints = {
}
}
The Test domain contains
class Test {
static belongsTo = User
static hasMany = [users:User]
static hasOne = [uni:Uni]
Integer testId // primary key
String testType
static mapping = {
table 'test'
id generator: 'assigned', name: 'testId', type: 'long'
testId column: 'test_id'
users joinTable:[name:'user_test', key:'test_id']
uni joinTable:[name:'user_test', key:'test_id'] // If I leave this out, everything is groovy
version false
}
static constraints = {
}
}
and the Uni domain contains
class Uni {
static belongsTo = Test
static hasMany = [tests:Test]
Integer uniId // primary key
String shortName
String fullName
static mapping = {
table 'uni'
id generator: 'assigned', name: 'uniId', type: 'long'
uniId column: 'uni_id'
version false
tests joinTable:[name:'user_test', key:'uni_id']
}
static constraints = {
}
}
If its not clear, what I'm trying to do is pull in the University ID, Test ID, and User ID to a table user_test to find based on the User ID which tests they have taken. Is there a simple way to do this?
The kinds of errors I'm getting lead me to believe that for some reason it is trying to perform all actions on the table test instead of user_test. For example,
Unsuccessful: alter table test add uni_id int not null
I'd like to be able to access the test and university information corresonding to the specific user via user.tests.testType and user.tests.uni.fullName or something to that extent. What am I doing wrong? More importantly, is there a better way to do this?! Thanks in advance!
Edit 1: something interesting I just thought of.. a user can have multiple tests, but the inverse isn’t true. A given test will never be shared among multiple people. So I think that changes things a bit.. I'll do some reading and post if I come up with anything new.
Edit 2: Here's the Role domain
class Role {
static belongsTo = User
static hasMany = [users:User]
Integer roleId
String shortName
String roleName
Integer roleLevel
static mapping = {
table 'role'
id generator: 'assigned', name: 'roleId', type: 'long'
roleId column: 'role_id'
users joinTable:[name:'user_role', column:'user_id', key:'role_id']
version false
}
static constraints = {
}
}
Edit 3: I am now trying to store all test information in the Test domain model and simply choose the Uni name to store as a field in Test, but am getting weird errors when I try this. My new files look like this
class User {
static hasMany = [roles:Role, tests:Test]
Integer userId
static mapping = {
table 'user_data'
id generator: 'assigned', name: 'userId', type: 'long'
userId column: 'user_id'
version false
roles joinTable:[name:'user_role', key:'user_id']
}
static constraints = {
}
}
and
class Test {
static belongsTo = User
Integer testId // primary key
Integer testTypeId
String testTypeName
String testUni
Date testDate
static mapping = {
table 'test'
id generator: 'assigned', name: 'testId', type: 'long'
testId column: 'test_id'
version false
}
static constraints = {
}
}
but now I'm getting the following error when I try to run it Caused by: org.hibernate.MappingException: Missing type or column for column[tests_test] on domain[User] referencing[Test]
Any idea what that's about?
Ok, one issue you have is that you're trying to share the User-to-Test association join table with the Test-to-Unit association. That's not going to work.
Lets look at it in database terms. I'm not an ASCII art expert, so I hope this diagram doesn't make your eyes bleed.
user_data (userId) |---|< (user_id) user_test (test_id) >|---| (testId) test
The diagram above shows the database implementation of the many-to-many association between the User and Test domain classes. You can see that the user_data.userId links to user_test.user_id and user_test.test_id links to test.testId.
Now here's where it starts to get weird. There are two different associations between Test and Uni: a bidirectional one-to-one and a one-to-many. I just don't understand that. But I want to illustrate an important issue with your join tables, so here it is.
test (testId) |---|< (test_id) user_test (uni_id) >|---| (uniId) uni
Because you're using the same join table (user_test) for two different associations you're asking GORM to create a table like this:
USER_TEST
- USER_ID
- TEST_ID
- UNIT_ID
GORM won't do that because join tables are supposed to have only two fields. Not only that, but also you're defining a many-to-many in database terms, and yet a bidirectional one-to-one and a one-to-many in GORM terms. Ouch!
TODO
The first change I recommend is to use a different join table for the Test-Uni association.
Finally got everything working (after a bit of modification in terms of the domain model)
class User {
static hasMany = [roles:Role, tests:Test]
Integer userId
static mapping = {
table 'user_data'
id generator: 'assigned', name: 'userId', type: 'long'
userId column: 'user_id'
version false
roles joinTable:[name:'user_role', column:'role_id', key:'user_id']
}
static constraints = {
}
}
and
class Test {
User user
Integer testId // primary key
String testType
String testUni
Date testDate
static mapping = {
table 'test'
id generator: 'assigned', name: 'testId', type: 'long'
testId column: 'test_id'
version false
}
static constraints = {
}
}
with
class Uni {
Integer uniId // primary key
String shortName
String fullName
static mapping = {
table 'uni'
id generator: 'assigned', name: 'uniId', type: 'long'
uniId column: 'uni_id'
version false
}
static constraints = {
}
}
So now what I'm doing is selecting the university from a drop down tab in my GSP and just saving it in Test as the string testUni. Then, the big change was removing all joinTables between the three and adding User user to Test. I'm still a little fuzzy on why what I was doing before didn't work, but I won't complain about a working app!

What is the best way to go about referencing multiple tables using slick 2.0?

I have these tables: USERS, USER_ROLES, ROLES, PERMISSIONS, ROLE_PERMISSIONS
I am implementing the:
AssignedRoles (M): returns the set of roles assigned to a given user;
So, if I was going to write the query for this function it would like something like this:
SELECT role_id FROM USER_ROLES WHERE user_id = 'M'
where M is the given user id, then I would look up each role by their id and return the Role object, or I would use a join, but that is not relevant here.
so where is what my UserRole model looks like:
case class UserRole(id:Long, userID:Long, roleID:Long)
object UserRoles {
class UserRoles(tag: Tag) extends Table[UserRole](tag, "USER_ROLES") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def userID = column[Long]("USER_ID")
def roleID = column[Long]("ROLE_ID")
def user = foreignKey("USER_ID", userID, TableQuery[Users])(_.id)
def role = foreignKey("ROLE_ID", roleID, TableQuery[Roles])(_.id)
def * = (id, userID, roleID) <> (UserRole.tupled, UserRole.unapply)
}
def retrieveRoles(userID:Long) : List[Role] = {
DB.withSession { implicit session =>
userRoles.filter(_.userID === userID).list
}
}
As expected retrieveRoles returns a list of UserRoles, but I want a list of Roles, so I woulds have to write another query that will take UserRole.roleID and find it in the roles table for each of UserRole that is returned. That is a lot of queries and I feel like there is a way that will to do this in one query. Any help from the Slick experts?
userRoles.filter(_.userID === userID).flatMap(_.role)