Grails with MongoDB not saving null value - mongodb

This is a customer domain class in Grails(v3.1):
class Customer {
static mapWith = 'mongo'
String id
String email
Boolean blacklisted
String name
String telephone
Date dateCreated
Date lastUpdated
String language = 'en'
static constraints = {
email nullable: false
blacklisted nullable: false
name nullable: true
language nullable: true
telephone nullable: true
}
static mapping = {
version false
}
}
I can insert and update into the Customer collection in MongoDB using this class, and it is working fine. The issue occurs when I try to save one of the fields with null value.
customer.telephone = null
customer.save()
Setting a value to null has no effect in the field in MongoDB collection, its value will remain set to the value before the update. For example, if the telephone is set to "1234567" and when I update it to null, the value in MongoDB remains "1234567".
I have tried using failOnError: true and flush: true in save(), both are not working. Any suggestions?

You could try using the mongo driver directly to see if it is a mongo issue or a Gorm issue.
Customer.collection.updateOne([_id:'the-id'],[telephone:null])

Related

TypeORM not setting NULL as DateString

I have the follwing property in my Customer entity (using a Postgres DB):
#Column({
type: "timestamptz",
nullable: true
})
#IsDateString()
cancelationDate: Date | string;
I want to be able to change the date (which works) but also to set it null (which does not work)
Works:
customer.cancelationDate = moment().add({years:100}).toISOString();
Throws error:
customer.cancelationDate = null;
It says property cancelationDate has failed the following constraints: isDateString
Is there any way to update this with null? Removing the #IsDateString() results in not updating the column at all.
Any hint is highly appreciated

replace ObjectId field with custom string for ObjectIdColumn in TypeORM/MongoDB

I have a NestJs REST API and use TypeORM with MongoDB. I want to create a entity called project. I started with a basic entity and I just read that I should use ObjectIdColumn instead of PrimaryColumn for MongoDB.
#Entity()
export class Project extends BaseEntity {
// The technical project name
#ObjectIdColumn({ generated: false })
public id: ObjectID;
// The display name
#Column({ unique: true })
public name: string;
// The project successor
#Column({ nullable: true })
public successorId: ObjectID;
// Configuration stuff for that project
#Column()
public configuration: object;
}
I would like to know if it's possible to replace that object id column with a primary column of type string. The id field is based on a special pattern, e.g. the name field
my awesome project
would result into
my-awesome-project
for the id field. Sure I made use of generated: false but I have to pass in a custom string instead of an ObjectID. Currently this is not possible because the docs say the ObjectID
Can be a 24 byte hex string, 12 byte binary string or a Number. http://mongodb.github.io/node-mongodb-native/2.1/api/ObjectID.html
So what needs to get done to use a custom string as an ID field? The only thing I can think of is creating a second field e.g. theRealId and treat it like the ID field and ignore the autogenerated ObjectId...
From what I've learnt, here is what you can do
#Entity()
export class UserEntity
{
#ObjectIdColumn()
_id: string;
#PrimaryColumn()
id: string;
// The display name
#Column({ unique: true })
public name: string;
#Column({ nullable: true })
public successorId: ObjectID;
#Column()
public configuration: object;
}
MongoDB will use _id as an internal id, that you do not expose through your program (and api, then)
You will work with the id, "normally', and it will be your primary key, generating automatically and so on
Source : personal learning, and Udemy course : NestJS Zero to Hero - Modern TypeScript Back-end Development

JPA EclipseLink: handle default value

I have the following column definition:
#Column(name="active", nullable=false, columnDefinition="BOOLEAN DEFAULT FALSE"
private Boolean active;
In the Postgres database the column active is defined as BOOLEAN NOT NULL DEFAULT FALSE
But when I insert a new record, without setting active, EclipseLink generates a null value for this field and the insert statement obviously fails because Postgres does not allow a null value for the NOT NULL column.
What am I doing wrong?
Well, if I define my field as
private boolean active;
then I will indirectly set the field to false. But I cannot use this trick with Date fields. So, I am looking for a solution which will work for all column types.
The columnDefinition is only used for the DDL creation and can be database specific. You may have problems switching the DB if you use it.
Using primitive types ensures that the value is not null, and without explicitly defining a value, the primitive's default is used. However, you can also define default values for non-primitive values by assigning them: private Boolean active = false;
That will also work with Date.
When you need complex default values you can use the PrePersist annotation:
#PrePersist
public void setDefaultValues() {
if (active == null) {
active = false;
}
if (value == null) {
//do complex stuff
}
}
If you NEVER are going to set the attribute, you can use #Column (insertable = false), if you set a value, this will be ignored anyway.
This is a very common setting on Date like
#Column(nullable = false, insertable = false, updatable = false, columnDefinition = "timestamp not null default CURRENT_TIMESTAMP")
#Temporal(TemporalType.TIMESTAMP)
private Date systemDate;

Insert Auto date when record created in mysql using grails

Actually i have manually entered records in mysql database-using grails but i want to show the date in a coloumn in same table.
Is there any solution for this
here is my controller class
class test {
String company_name
String contact_person
Integer phone_no
String status
String place
String address
static constraints = {
company_name(nullable:false)
contact_person(nullable:false)
phone_no(uinque:true,nullable:false)
status(nullable:false)
place(nullable:false)
address( nullable:false )
}
}
Grails provides automatic timestamps via the "dateCreated" property:
Automatic timestamping
If you define a dateCreated property it will be set to the current
date for you when you create new instances. Likewise, if you define a
lastUpdated property it will be automatically be updated for you
when you change persistent instances.
(From the Grails user guide: Events and auto timestamping)
Have a look at dateCreated and lastUpdated in autoTimestamp property in GORM.

Grails custom validation scenarios

I just started looking at grails, I used to work mainly with PHP before, so my question is what is the best way of adding custom validation scenarios to a form. So lets say we have all the constraints in the domain but under a certain controller action where a form is bound to the domain we want to add an extra custom validation of some sort (for argument sakes, lets say we have a date and only in this scenario it should be more than 2 weeks in the future). Whats the best approach of doing that?
Thanks!
For you requirement you can using a Command Object with constraints:
#grails.validation.Validateable
class CommandObject {
Date date
static constraints = {
date(/*constraint here*/)
}
}
Edit:
Concerning your second question, yes you can share constraints from your domain object to your command object using importFrom [EntityName], see the example from the doc:
Domain object:
class User {
String firstName
String lastName
String passwordHash
static constraints = {
firstName blank: false, nullable: false
lastName blank: false, nullable: false
passwordHash blank: false, nullable: false
}
}
Command object:
class UserCommand {
String firstName
String lastName
String password
String confirmPassword
static constraints = {
importFrom User
password blank: false, nullable: false
confirmPassword blank: false, nullable: false
}
}
Sharing Constraints
I suggest you do the form validation using jquery before it reaches the controller. If you want, you can also do individual validation on the gsp itself (ei. checking that the input field is required, accepts only emails, accepts integer only etc.). You can even do this on the controller. But I think form validation using jquery is already enough :)