Gorm change primary key, not found with id null - grails

I have read tons of questions about this and it seems that nobody gets it to work.
I am using grails, and I am creating a class that doesn't have id as the primary key.
I get the message "usuario not found with id null". this is the code of my domain class:
class Usuario implements Serializable{
String nombre
String celular
String telefono
String apellido
String password
String nick
static mapping = {
table 'Usuarios'
version false
id composite: ['nick']
}
}
I also tried the normal way with the:
static mapping = {
table 'Usuarios'
version false
id name: 'nick'
}
It actually maps the table the way I want to with the natural key and everything, it inserts the new usuarios, but the gui is incapable of retrieving any objects and shows the error: "usuario not found with id null"
I tried to modify the show(Long id) method, but it wont help either, this is my show method from the controller:
def show(String nick) {
def usuarioInstance = Usuario.get(nick)
if (!usuarioInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'usuario.label', default: 'Usuario'), nick])
redirect(action: "list")
return
}
[usuarioInstance: usuarioInstance]
}

You need to specify the assigned generator:
static mapping = {
...
id column: 'nick', generator: 'assigned'
}
Plus it might be wise to add the following constraints:
static constraints = {
nick blank:false, nullable:false, unique: true
}

Related

Property xxx is type-mismatched

I'm trying to build simple CRUD application using Grails. I'm absolutely new to this framework. My CRUD table has few properties, connected to a local database and it works so well except it can't load pictures in it. I get a error that it's type mismatched. How to solve it?
My controller class is below:
class Person
{
int id
String name
String address
byte[] profilePic
}
static constraints
{
profilePic maxSize :204800
}
static mapping
{
table 'all_users'
version false
columns
{
id column: 'id'
name column: 'name'
address column: 'address'
profilePic column: 'profilepic'
}
}
Domain Code
class Person
{
int id
String name
String address
String profilePic
}
static mapping
{
table 'all_users'
version false
columns
{
id column: 'id'
name column: 'name'
address column: 'address'
profilePic column: 'profilepic'
}
}
Controller Code
def save(){
def person = new Person(params)
person.save flush: true, failOnError: true
redirect action: "show", id: person.id
def downloadedfile= request.getFile('profilePic')
String profilePic = "D:/Your Grails Applications/grails-app/assets/images/" + person.name + ".jpg"
downloadedfile.transferTo(new File(profilePic))
}
View Code
<input type="file" name="profilePic"/>
Take a look http://docs.grails.org/latest/guide/single.html#uploadingFiles and How to store a file in the database with Grails

Cannot redirect for object [ManageVehicle : (unsaved)] it is not a domain or has no identifier. Use an explicit redirect instead

This is my domain.
import org.apache.commons.lang.builder.EqualsBuilder
import org.apache.commons.lang.builder.HashCodeBuilder
class ManageVehicle implements Serializable {
String vehicle
Short truckKey=0
Short siteID
Integer unitID
String wheelConfig
String model
Short period=0
String usid=UUID.randomUUID().toString()
//static belongsTo = [wheelConfig : TTType,model:TTModel]
int hashCode() {
def builder = new HashCodeBuilder()
builder.append truckKey
builder.append siteID
builder.toHashCode()
}
boolean equals(other) {
if (other == null) return false
def builder = new EqualsBuilder()
builder.append truckKey, other.truckKey
builder.append siteID, other.siteID
builder.isEquals()
}
static mapping = {
table 'TF_Truck'
version false
truckKey column :'TruckKey'
siteID column :'SiteID'
id composite:['truckKey','siteID']
vehicle column: 'TruckID' ,sqlType: 'nvarchar'
wheelConfig column: 'TypID',sqlType: 'tinyint'
model column: 'ModID' ,sqlType: 'tinyint'
unitID column: 'McmID',sqlType: 'tinyint'
period column: 'Period'
usid generator: 'assigned', column:'USID', sqlType:'uniqueidentifier'
}
static constraints = {
period nullable: false
truckKey nullable: false
siteID nullable: false
}
}
And my save method in controller is .
def save(ManageVehicle manageVehicleInstance) {
manageVehicleInstance.siteID=RequestContextHolder.currentRequestAttributes().getAttribute("SiteID",RequestAttributes.SCOPE_SESSION) as Short
if (manageVehicleInstance == null) {
notFound()
return
}
if (manageVehicleInstance.hasErrors()) {
respond manageVehicleInstance.errors, view:'create'
return
}
manageVehicleInstance.save(flush:true,failOnError: true)
request.withFormat {
form {
flash.message = message(code: 'default.created.message', args: [message(code: 'manageVehicle.label', default: 'Manage Vehicle'), manageVehicleInstance.id])
redirect manageVehicleInstance
}
'*' { respond manageVehicleInstance, [status: CREATED] }
}
}
while i am applying save operation on this domain i am getting following exception .
Message: Cannot redirect for object [ManageVehicle : (unsaved)] it is not a domain or has no identifier. Use an explicit redirect instead
Suggest me some solution.
I guess that Grails cannot handle composite id in redirection.
I have two options in my mind to fix that case
Create id field for your domain class by removing id line from mappings
Implement custom redirection for your saved object like
redirect(action:'show', params:[truckKey:manageVehicleInstance.truckKey,siteID:manageVehicleInstance.siteID])
With 2. option you may also have to implement custom object loading into 'show' action using composite id like def manageVehicleInstance = ManageVehicle.findByTruckKeyAndSiteID(params.truckKey, params.siteID).

Grails: Legacy DB - Record with composite Id won't update

I'm having problems trying to update a record on a Grails 2.3.7 Project
I don't want to modify the fields that are part of the composite Id, I just want to update the other fields.
Just one class, few properties, but every time I try to update, it throws me the "not unique error" when this lines runs:
personInstance.validate()
if (personInstance.hasErrors()) {
respond personInstance.errors, view:'create'
return
}
My class looks like this:
class Person implements Serializable {
static constraints = {
name(unique: lastName)
}
static mapping = {
id generator: 'assigned'
id composite: ["name", "lastName"]
}
//Override equals and hashcode methods
boolean equals(other) {
if (!(other instanceof Person)) {
return false
}
other.name == name && other.lastName == lastName
}
int hashCode() {
def builder = new HashCodeBuilder()
builder.append name
builder.append lastName
builder.toHashCode()
}
String name
String lastName
String description
}
And the controller action:
def update() {
def personInstance = Person.get(new Person(name:params.name, lastName:params.lastName))
personInstance.properties = params
personInstance.validate()
if (personInstance.hasErrors()) {
respond personInstance.errors, view:'create'
return
}
personInstance.save flush:true
request.withFormat {/*etc...*/}
}
When I use validate(), it throws me a Grails unique key error, when I avoid validation its a BD not unique PK error.
Is like Grails didn't know if I want to do an insert or an update when I personInstance.validate().
Is there a way to manage this in a correct way that I'm not seeing?
Or am I forced to avoid validation?
am I doing something wrong?
Thanks in advance.
I believe the GORM mapping DSL expects just one id definition. Try combining your two id lines into just this one:
id generator: 'assigned', composite: ["name", "lastName"]
Also, in addition to implementing Serializable, your domain class should override equals and hashCode, as described under "Composite Primary Keys" here: http://grails.org/doc/latest/guide/single.html#identity

Grails clear hasMany entries and add new ones error?

I am currently working on a grails applications and I have a list of addresses that are attached to an account. Basically what I want to do is when the Account is edited is displays a current list of all the attached Addresses and then I can delete/add as many as I want from the view. When this data is captured it is picked up by the controller and what I want to do is to be able to clear all of the current Addresses from this account and then create the list again with what exists on the view, my code is below:
Account Domain:
class Account {
String name
Date dateCreated
Date lastUpdated
static hasMany = [addresses:Addresses]
static mapping = {
addresses cascade:"all-delete-orphan"
}
def getAddressesList() {
return LazyList.decorate(
addresses,
FactoryUtils.instantiateFactory(Addresses.class))
}
static constraints = {
name(blank:false, unique: true)
}
}
Address Domain:
class Addresses {
int indexVal
String firstLine
String postcode
String area
static belongsTo = [account:Account]
static mapping = {
}
static transients = [ 'deleted' ]
static constraints = {
indexVal(blank:false, min:0)
}
}
Account Controller:
def update() {
def accountInstance = Account.get(params.id)
if (!accountInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'account.label', default: 'Account'), params.id])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (accountInstance.version > version) {
accountInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'subscriptions.label', default: 'Subscriptions')] as Object[],
"Another user has updated this Account while you were editing")
render(view: "edit", model: [accountInstance: accountInstance])
return
}
}
accountInstance.properties = params
accountInstance.addresses.clear()
accountInstance.save(flush: true)
....
}
Error:
A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses. Stacktrace follows:
Message: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses
This error seems to be occurring in the controller on line:
accountInstance.save(flush: true)
I have tried several different way to get this to work and would really appreciate some help.
So it seems like you have done some work that Grails can do for you.
class Account {
String name
Date dateCreated
Date lastUpdated
List addresses
static hasMany = [addresses:Address]
static mapping = {
addresses cascade:"all-delete-orphan"
}
static constraints = {
name(blank:false, unique: true)
}
}
class Address {
String firstLine
String postcode
String area
static belongsTo = [account:Account]
}
This will produce the effect you want of having addresses being a list.
I've found either
instance.addresses = null
or
instance.addresses.clear()
to work for me
When you define addresses cascade:"all-delete-orphan" in Account class you don't need static belongsTo = [account:Account] in Addresses. So just try to remove that statement and test your code. See related link.

Grails 2.1 Join Query

I m new user in Grails. I don't know how to write projection query. Here is my code. please anyone help me for grails projection query.
From Join table I want to find username which is consist in user table
Given the following example domains:
class User{
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static mapping = {
table 't04t001'
id column: 'f_account_id'
username column: 'f_username', length: 10
password column: 'f_password', length: 100
enabled column: 'f_account_active'
accountExpired column: 'f_account_expired'
accountLocked column: 'f_account_locked'
passwordExpired column: 'f_password_expired'
version column: 'f_revision'
}
}
class Role{
String role
static mapping = {
table 't04t003'
id column : 'f_role_id'
role column : 'f_role'
version column : 'f_revision'
cache true
}
}
class UserRole implements Serializable {
User user
Role role
static mapping = {
table 't04j002'
id composite : ['role', 'user']
role column :'k_role_id'
user column :'k_user_id'
version false
}
}
I can't figure out how to build the criteria to find all the user. I tried the following:
def criteria = UserRole.createCriteria()
def list = criteria.list {
projections {
user{
ilike('username', 'omar')
}
}
}
In console mode i have seen this query with message
Hibernate:
select
this_.k_role_id as k1_3406_0_,
this_.k_user_id as k2_3406_0_
from
t04j002 this_
where
(
lower(user_alias1_.f_username) like ?
)
However, it says Unknown column 'user_alias1_.f_username' in 'where clause'.
But i cant figure out this(user_alias1_) alias
I am not exactly clear on what you want to retrieve from which table. So based on your criteria query, here is how to retrieve user from the UserRole table.
def criteria = UserRole.createCriteria()
def result = criteria.list {
projections {
property("user")
}
user {
eq("username", "omar") //strict match
}
}
return result;
What this does is it builds a list that has the user.username as omar. By default the result will be the UserRole object, but to get user object instead we used projections.
Update:
Your Domain class seems a bit out of grails conventions. Why not user something like this?
//User.groovy
class User {
String username
// ..
static constraints = {
username blank: false, nullable: false, maxSize: 10
}
}
//UserRole.groovy
// Since you are using composite keys, we have to implement serializable. But is there a need for composite key in your situtation?
class UserRole implements Serializable {
User user
// ..
}
In you service class
// UserRoleService.groovy
def getUser(String username) {
def criteria = UserRole.createCriteria()
def result = criteria.get {
projections {
property("user")
}
user {
ilike("username", username)
}
}
return result;
}
And to call the service method from controller,
// ExampleController.groovy
class ExampleController {
def userRoleService
def index() {}
def someThing(String username) {
def user = userRoleService.getUser(username)
println user?.username
// ..
}
}

Resources