How can I update my existing database table using domain class in grails 3.3.0? - grails

I would like to add new column in my existed table using domain class but it is not happening. if I use create-drop in application.yml file then it works but at the same time I lost my data. I needed to keep the data as well as I needed to add new column by updating domain class property in grails 3.3.0 and SQL Server 2012
package com.alumni
class Student
{
String studentId
String studentName
String age
static constraints = {
}
}
Database is not updating with column address

It's unclear from your code snippet, but it sounds like you're trying to add
String address
Note that columns are made NOT NULL by default, so if data exists in the table, it's attempting to add a non-nullable column, with null data on every row, so the column will fail to create. You need to allow this column to be nullable in the constraints block as well
static constraints = {
address(nullable: true)
}
If you add that, the column should create successfully.

Related

how to make first column nullable in one to many relationship join table?

There seems to be a change in behavior from grails 2 to grails3. When i create a one to many relationship like
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
}
It will create a join table with columns author_books_id and book_id. In grails 3 it also adds a not null constraint on the first column. In grails 2 not null constraint is not applied. So when i upgrade to grails 3 it is breaking because there are already few records that have first column values to null. It works fine in grails 2 but with grails 3 the first column should not be null. Furthermore the join table is read only so i cannot remove the rows will null first column values. Is there a way to make the first column nullable = true by making changes in domains and not directly in migration file.
The code was extracted from the grails documentation. Please scroll down to one to many section.
6.2.1.2 One-to-many
http://docs.grails.org/3.0.17/guide/GORM.html
Try changing your Book class to this
class Book {
String title
Author author // this creates the belongs to relationship
}
static constraints = {
author nullable:true
}
Also when you recompile the code make sure to delete previous table and start fresh. Grails will not alter any table to delete anythings. It only adds new stuffs.

Mapping a generated database column to a Grails domain class property

In my Grails 2.5.X app, I have a domain class that looks like this:
class FormData {
String submittedFields
Boolean submitted
static constraints = {
submittedFields nullable: true
}
static mapping = {
// can I do something here to map submitted to a generated
// column of the form_data table
}
}
I would like to map the submitted property to a generated column of the form_data table, i.e. a column that would be created by the SQL statement
alter table form_data add submitted tinyint
GENERATED ALWAYS AS (if(submitted_fields is null,0,1));
Specifically, this generated column should be created when I create the schema from the domain model, e.g. by running the schema-export script.
A consequence of submitted being mapped to a generated column is that the corresponding domain class property should be read-only, or at least, assigning a value to it should have no effect.
If you want to handle the value of the column on database side only, and dont want it to be inserted or updated from grails/hibernate side. you can make the column as insertable:false updatetable:false
static mapping = {
submitted insertable:false, updateable:false
}
Now, even if the value is changed in grails, the new value will not be updated in database.

grails validation when fetching rows

Is it possible to fetch a default value in grails if a column is null? If I were to represent following query via grails domain object then how could I achieve it:
SELECT IFNULL(empsalary,0.00) from Employee;
Domain object:
class Employee{
Integer id,
Float empsalary
static constraints = {
id unique: true, blank:false
empsalary nullable:true
}
}
making empsalary nullable false isn't an option due to existing data
validator on empsalary seems to work when inserting rows but not while data fetch
we can consider writing say getEmpSalary() method on domain and perform check there but there are several other fields we need to do this so trying to avoid massive code changes
If you want a default value to come out of the database without having to code anything into your classes, I suggest you update every row where it is null and set it to 0 in the database. If data is getting inserted from another application and that application is allowing a null value, put a 'DEFAULT 0' on your database column.
Grails also offers an "afterLoad" event which is run when a domain object gets loaded from the database. See the documentation here: http://grails.org/doc/2.3.7/guide/GORM.html.
I think you can do this with HQL:
def salary = Employee.executeQuery('SELECT COALESCE(empsalary, 0.0) FROM Employee')[0]
See this SO Question.
Please try setting Float empsalary = 0.0 in your domain object.

How to update schema on a local database?

In the next version of my app, I need to update a column from NVarChar(16) to NVarChar(255) on one of the tables in my local database. Currently the column is marked up as follows:
[global::System.Data.Linq.Mapping.TableAttribute()]
public partial class Message : INotifyPropertyChanged
{
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_Name", DbType = "NVarChar(16) NOT NULL", CanBeNull = false)]
public string Name
{
...
}
}
All examples that I've seen point to the DatabaseSchemaUpdater class, however, it has methods to Add a column, but none to update the length of the column.
How do I update the column length?
It turns out the API does not allow you to do that. Or drop columns. The only thing you could do is add a new column (it must be nullable for some reason), use it and ignore the ones you no longer want.
Weak API design.

Change model after database is created on EF4 code only

Hey, sorry for my bad english...
Using EF4 code-only, I have created some POCO classes and my database was generated from that. All worked fine, I inserted some data on the tables but now I need to create a new property on one of my classes. If i just create it, the application give me the exception:
{"The model backing the 'TestContext' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the RecreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data."}
I tried to create manually the field on the table, but it is still complaining... does someone know if there is a way and if so how can I manually update the database schema (i don't want to recreate it because i already have data) to match the model?
It should work if you make sure that your new column match exactly your new property.
For example, if you add a property NewProp
public class MyEntity
{
[Key]
public int Id;
public string PropA;
public int PropB;
public int NewProp;
}
then in your database table MyEntities, you would add a column NewProp of type int not null.
What you can do to check if the column you add is correct, is to rename your database, then let Code-First recreate the database and see what's different between the original and new databases.
EF generates partial classes. So you can add new properties(fields) in another partial class.

Resources