I have 2 classes named User.groovy and Employee.groovy and I used MYSQL to save the data. What I want is to create a new User account and save it to the User table and also save some of the data to Employee table. How can I do this? I've tried extending the user to Employee but the data only saved to User and not to Employee. But If I don't extend the User, the data is only saved to Employee. What should I do so that the data simultaneously saves to two database tables at the same time? Please help me.
Actually have this in my class user:
class User {
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
.....}
and employee:
class Employee {
String name
String email
String jobDesc
....}
So what should I do next? I'm sorry for this, I'm still starting to learn grails.
Grails paradigm (as far as scaffolding is concerned) is one form - one object. As long as you stick to this paradigm, you get all the goodies, such as input validation and error reporting for free (you may also consider using the Fields plugin here http://grails.org/plugin/fields).
However, sometimes you need to collect info and create two or more objects through single form. Usually this happens when you need to initiate new subscription and collect info for both subscription details (say, Subscription entity) and user info (User entity). This is where command objects come to rescue.
http://grails.org/doc/latest/guide/theWebLayer.html#commandObjects
So, instead of expanding/bending SubscriptionController or UserController (or UserController and EmployeeController, as per your example), you create SignUpController, which handles SignUpCommand object. The SignUpCommand object is not intended to be saved, it is used as a backing object for the SignUpController.create form. When it validates, you use the signUpCommand object data to initialize 2 domain objects (that is Subscription and User) and save these objects individually within the same transaction.
You can either delegate the save operation to a service say,
if (signUpCmd.validate()) {
SignUpService.save(signUpCmd))
}
or create and save both objects right on the spot within controller
if (signUpCmd.validate()) {
Subscription subscription = new Subscription(plan: signUpCmd.plan, ...)
subscription.save()
User user = new User(username: signUpCmd.username, ...)
user.save()
}
it is mostly matter of taste and style.
Instead of calling save() directly to your user instance, call a service class that saves both the user and the employee in one atomic operation. Like, for instance:
class UserController {
/*Injection of your service in the controller class*/
def userService
And then in the save action in this same controller:
userService.save(user) // userService.save(params)
And inside this service method you will extract the data (user or params, whatever floats your boat) you want to save in a different table as long as the usual user object.
Related
I have a database with some complex relationships mapped and populated with a large amount of data. My requirement is that I need to use this database with Swift-Vapor server.
So that I created a model object (with Fluent framework constructs) similar to the database schema, in order to handle data flows between the vapor server and db.
When it comes the time to link database table(users table) with the model(User model), I found this method, which should implement inside the model class.
static func prepare(_ database: Database) throws {
try database.create("users") { users in
users.id()
users.string("name")
}
}
Since I don't need to define a schema for already existing db, this prepare method just left unimplemented.
The result is that I just can't interact with db, for any operations like userObj.save()
The same thing I achieved with Swift-Perfect Server with the help of the following method implementation inside the model object. This was done with the help MySQLStORM in Perfect.
// Map the model to the database table "user"
override open func table() -> String {
return "user"
}
What I'm looking for is -> Is there any option like this available in Vapor so that I can map model object to a database table?
Got a solution while discussing this issue in Slack community, tried out and working fine.
Solution:
In the model class (say User), the prepare method can be left unimplemented, like
static func prepare(_ database: Database) throws {
}
But should add a static variable entity which will have the table name mapped, like
final class User: Model {
static let entity = "users"
...
}
And finally, we should add the model to the droplets preparations array, like
// Let the User be your model object
drop.preparations.append(User.self)
So that we can use any existing database with complex relations or pre-populated data tables to map with the model object, without constructing tables from model object.
I am looking for a spring based solution for this problem. I have solved this in crude way but looking for better solution.
I have a client server architecture application.
Based on user permission, I am able to :
get list of fields for loggedin user which he is not permitted to write.
get list of fields for loggedin user which he is not permitted to read.
Now, how can I verify that the object to be written into database is as per user permission in an efficient way. I can iterate over fields, check if its value is different from that stored in db and reject accordingly. Is there any effecient way ?
Example:
One domain entity "Account" which is stored in MongoDB.
class Account {
String name;
String email;
String mobile;
}
Corresponding DTO Object to be returned to client
class AccountDto {
String name;
String email;
String mobile;
}
Two User -> User A, User B
Scenario:
User A can edit [ name ] but not email, mobile.
User A can view [name, email] but not mobile.
How can I design to return only those field which he is permitted to view. I donot want to create numerous DTO based on every user permission.
How can I write a code to check that the Object to be written to database is valid as per permission assigned to loggedin user. I dont want to iterate over fields and check field permission and then discard. Expensive operation.
My solution: Whenever user is going to write to db, I can fetch the existing record , compare with the record he is going to write and reject if field value is changed if he has not that permission. But this adds DB read cost and is not that generic solution.
I am making a simple REST API in front of a NoSQL database that stores records as documents similar to JSON (but not exactly the same). Each record has some fields, including id for the database, and also including some derived fields, like dateCreated.
Any time I GET anything, I want to return the objects with all the fields.
// GET /users returns an array of these in JSON
// [{id:"xxx", name:"Bobby", dateCreated:"YYYY-MM-DD"]
data User = User { id :: String, name :: String, dateCreated :: XXX }
But any time I POST or PUT anything, they client should send an object with the id field and any derived fields missing. The database is responsible to create the id when I save it, and I would create some derived fields
// POST /users would need you to post only the name.
// {name:"Henry"}
data PartialUser = PartialUser { name :: String }
If resource represents objects of type User, what should I call the thing client is sending to me? Would you make all the derived fields Maybe values? Or would you create a second object called PostedUser or something?
It can be many things:
a request body
the representation of the intended resource state of the client
a command DTO which you can send to the domain logic in order to process it by CQRS
I would make it CreateUser command, but if you don't want to use CQRS and DDD, then you would probably call it as PartialUserRepresentation, or you don't create a data structure, just use the properties to create a new User entity. Ofc. if you use entities.
So I would say it depends on the architecture of your system.
I have a user object called UserSystem, which is created by a static factory class that returns User Systems. Because the factory class only exists to create this object once, then disposes, is it possible to associate my persisted UserSystem object with another instance of my database context that I create at a later point?
I would like to avoid having to query my new DatabaseContext to find the matching UserSystem object and simply associate the persisted user object from the first DatabaseContext class with my new DatabaseContext.
Thanks!
George
You probably want to Attach your object to the DataContext. There are many articles about this, for example this one. Be careful though - this method is not intended to allow you to attach objects that are already attached to another DataContext, it is only for deserialized objects that are completely unattached, which I assume is what you have.
You may use the Attach method on the Table<T> object to insert a detached data object into it. You may insert it in a modified state, or in an unmodified state. If you insert it in a modified state, the next SubmitChanges() call will include it.
The Table(Of TEntity) Attach method overloads
I have a L2S generated class called Accounts, I have a L2S class called UsersInAccounts I need to add a function call AddUserToAccount(accountid, userid) should/could this function be added to the partial Accounts class I have created or are partial classes used for getting data rather than editing data
public partial class Account
{
public void addUser(Guid userid)
{
// code
}
}
I don't think that what you are doing is a problem. In your code, you'd probably have an Account instance that you want to do things with so being able to do this:
Account theAccountIWant = GetTheAccount();
theAccountIWant.addUser(myUsersGUID);
...seems pretty intuitive. It might be an idea to do some error trapping inside your addUser method and pass back some sort of success status but that's another discussion.
edit: As advised, if you then retrieve a User object and want to attach it to the Account using the AccountUsers property then this is no use unless you pass the DataContext in.