Grails: text instead of varchar - mysql

I need the MySQL column type for the String field in my Domain class to be TEXT or VARCHAR(3000), but nothing I try seems to work - it remains VARCHAR(255). I've tried
static mapping = {
longString type: 'text'
}
and
static mapping = {
longString sqlType: 'text'
}
and
static constraints = {
longString (blank: true, nullable: true, maxSize: 3000)
}
and
static constraints = {
longString (blank: true, nullable: true, size: 0..65535)
}
MySQL Server version 5.0.95, Grails 2.4.3.
I'm totally mystified and would appreciate any help..

You need to define the type of the column in the mapping block rather than constraints. Assuming the name of the property is longString, add this
static mapping = {
longString type: 'text'
}
This will create a column with a MySQL type of longtext.
To verify that this works, try dropping your database, create a new (empty) database, restart the app and check the type of the column that is created. See this example for reference.

Related

Unable to create BLOB/Binary types with LoopBack 4

I'm trying to use Loopback for my new projects, but I've been facing some problems...
I have the habit of storing my UUIDs ID in a binary format at my databases, here's an example:
#model({
settings: { mysql: { table: 'application' } },
})
export class Application extends Entity {
#property({
type: 'buffer',
required: true,
generated: false,
id: true,
dataLength: 16,
})
id: BinaryType;
[...]
}
But when I try to do the migration, I've been receiving that error from mysql:
"BLOB/TEXT column 'id' used in key specification without a key length"
I really tried everything and nothing works. Hope that you'll be able to help me!
Thanks a lot!
I'll show the answer for this question that I made.
Just define your model with the following info:
#property({
required: true,
mysql: {
columnName: 'application_id',
dataType: 'VARBINARY',
dataLength: 16,
nullable: 'NO'
}
})
application_id: string;
It worked like a charm for me :)
Thank you all!

Not store updatedAt with sequelize model

When I store models in my MySQL DB, they are immutable. As a result I can see the need for the createdAt column in my tables, but I don't need the redundant updatedAt column. Can I configure sequelize not to store updatedAt time and then can I drop the column from my table?
Looking at the documentation regarding your situation
If you want sequelize to handle timestamps, but only want some of them, or want your timestamps to be called something else, you can override each column individually:
const Foo = sequelize.define('foo', { /* bla */ }, {
// don't forget to enable timestamps!
timestamps: true,
// I don't want createdAt
createdAt: false,
// I want updatedAt to actually be called updateTimestamp
updatedAt: 'updateTimestamp',
// And deletedAt to be called destroyTime (remember to enable paranoid for this to work)
deletedAt: 'destroyTime',
paranoid: true
})
So in the above example, just set timestamps to be true but then createdAt to be false
Found my own answer at http://docs.sequelizejs.com/manual/tutorial/models-definition.html#configuration, I should use updatedAt: false in my model definition.

Can't update table in mysql in a Grails application

I have this weird problem. I have a User domain class in a Grails app. The class is as follows:
class User {
transient springSecurityService
String username
String name
String password
String email
String company
Date activationDate
String contactPhone
boolean enabled
boolean passwordExpired = false
boolean accountExpired
boolean accountLocked
boolean isDeleted=false
boolean isPrimary
String jobTitle
String jobFunction
String deskPhone
String mobile
String profilePicURL
boolean isLinkExpired=false
UserType userType
Date dateCreated
Date lastUpdated
static constraints = {
password nullable: true
company nullable: true
email blank: false, unique: true
name nullable: true
activationDate nullable:true
username nullable: true
enabled nullable: false
isDeleted nullable: false
passwordExpired nullable: false
jobFunction nullable:true
jobTitle nullable:true
contactPhone nullable:true
mobile nullable:true
profilePicURL nullable:true
deskPhone nullable:true
userType nullable:true
}
static auditable = true
static mapping = {
password column: '`password`'
tablePerHierarchy false
cache true
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
And there is a method activeDeactiveUser which enables/disables user authorization for some functionality as follows:
def activeDeactiveUser(String username) {
def user = User.findByUsername(username)
if (user.enabled == false)
user.enabled = true
else
user.enabled = false
if (user.validate()) {
user.save(flush: true, failOnError: true)
} else {
user.errors.allErrors.each {
print it
}
}
def userJson = new JSONObject()
userJson.put("isEnabled", user.enabled)
return userJson
}
When the app is running on localhost, the table is updating fine. But when the same code is running on server, the table fails to update. I don't know why it's behaving like this.
The app isn't raising any exception on the save method on localhost. May be the problem is with different versions of mysql on my machine and the server. Is there any the to debug the app while it is running on the server?
The app is hosted in an AWS EC2 instance running Ubuntu 14.04 and Grails version 2.4.3. The database is stored in an AWS RDS instance running mysql 5.5.40.
there are many reasons for it - I think you need to provide more information for yourself and in this thread so we can help.
I suggest, first add log information by one of the options:
you can add logSql to dataSource file:
dataSource {
logSql = true
}
to produce far more readable SQL commands than simply logSql would do add the following properties in DataSource.groovy:
hibernate {
format_sql = true
use_sql_comments = true
}
Then, add the following log4j settings to Config.groovy:
log4j = {
debug 'org.hibernate.SQL'
trace 'org.hibernate.type'
}
The first setting logs the SQL commands, the second one logs the bound parameters and the bindings of the result set.
the issue can also be related to schema update - so maybe your local DB schema is not in sync with server one. you ned to check field type and constraints.

Grails 2.4.4: Database record updates on createCriteria().list()

I am having a weird issue. I have a Domain object:
class MyClass {
String name
Boolean new = true
String number
String type
Byte[] data
Date dateCreated
Date lastUpdated
static belongsTo = [
other: MyOtherClass
]
static mapping = {
table 'my_classes'
data column: "data", sqlType: "MEDIUMBLOB"
}
static constraints = {
data maxSize: 8000 * 66
number nullable: true
}
}
In the Controller I have (edited to show entire method):
def list = {
def myOtherClasses = MyOtherClass.getAll()
if ( !params.max ) params.max = 20
if ( !params.sort && !params.order ) {
params.sort = "new"
params.order= "desc"
}
def myClassCount = MyClass.createCriteria().count() {
'in'( 'other', myOtherClasses )
order( params.sort, params.order )
}
def myClassList = MyClass.createCriteria().list() {
'in'( 'other', myOtherClasses )
order( params.sort, params.order )
}
return [ myClassList: myClassList, myClassCount: myClassCount ]
}
The result if fine and the view is correct. But each time this code runs, the data property isDirty, so version is incremented, and lastUpdated is updated.
The data property is holding audio data, but I don't think that is relevant.
I can't figure out what is going on here. So my question is, how do I make it stop updating?
Using:
Grails 2.4.4
Hibernate 3.6.10.18
MySQL 5.7.9
Thanks in advance :)
After much research and testing, and a few great articles, I have found a solution:
Instead of using type Byte[] in the Domain Object, I use java.sql.Blob, and removed the sqlType in the mapping.
In the controller, I had to make a few changes to access the Byte[] data from the Blob, but that was easy.
I still don't know why this was happening, and I couldn't find any info on it, but it is working as expected now.

A Sequelize column that cannot be updated

Is it possible to create a column on a MySQL table using Sequelize that can be initialized when creating a new row, but never updated?
For example, a REST service allows a user to update his profile. He can change any field except his id. I can strip the id from the request on the API route, but that's a little redundant because there are a number of different models that behave similarly. Ideally, I'd like to be able to define a constraint in Sequelize that prevents the id column from being set to anything other than DEFAULT.
Currently, I'm using a setterMethod for the id to manually throw a ValidationError, but this seems hackish, so I was wondering if there's a cleaner way of doing this. Even worse is that this implementation still allows the id to be set when creating a new record, but I don't know a way around this as when Sequelize generates the query it calls setterMethods.id to set the value to DEFAULT.
return sequelize.define('Foo',
{
title: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
notEmpty: true
}
}
},
{
setterMethods: {
id: function (value) {
if (!this.isNewRecord) {
throw new sequelize.ValidationError(null, [
new sequelize.ValidationErrorItem('readonly', 'id may not be set', 'id', value)
]);
}
}
}
}
);
Look at this Sequelize plugin:
https://www.npmjs.com/package/sequelize-noupdate-attributes
It adds support for no update and read-only attributes in Sequelize models.
In your specific case, you could configure the attribute with the following flags:
{
title: {
type: DataTypes.STRING,
allowNull: false,
unique : true,
noUpdate : true
}
}
That will allow the initial set of the title attribute if is null, and then prevent any further modifications once is already set.
Disclaimer: I'm the plugin author.