Cloned the code from the tutorial : Database per Tenant Multi-Tenancy
I went into the completed project and began playing around with things.
I understand how the application is resolving tenant ids and connecting to varying datasources without difficulty.
What is leaving me scratching my head is how to create other types of relationships.
The example shown in the tutorial demonstrates a many-to-many relationship. What I'm looking to use is a unidirectional one-to-one relationship.
Naturally, the way I thought to do this was to make a simple change. I changed the Vehicle.groovy file and VehicleService.groovy
Here are my versions of the files:
//Vehicle.groovy
package example
import grails.gorm.MultiTenant
class Vehicle implements MultiTenant<Vehicle> { // <1>
String model
Integer year
Engine engine
static constraints = {
model blank:false
year min:1980
}
}
//VehicleService.groovy
package example
// tag::class[]
import grails.gorm.multitenancy.CurrentTenant
import grails.gorm.services.Join
import grails.gorm.services.Service
import grails.gorm.transactions.Transactional
import groovy.transform.CompileStatic
@Service(Vehicle) // <1>
@CurrentTenant // <2>
@CompileStatic
abstract class VehicleService {
// end::class[]
// tag::queries[]
@Join('engine') // <1>
abstract List<Vehicle> list(Map args ) // <2>
abstract Integer count() // <3>
@Join('engine')
abstract Vehicle find(Serializable id) // <4>
// end::queries[]
// tag::save[]
abstract Vehicle save(String model,
Integer year)
// end::save[]
// tag::update[]
@Transactional
Vehicle update( Serializable id, // <5>
String model,
Integer year) {
Vehicle vehicle = find(id)
if (vehicle != null) {
vehicle.model = model
vehicle.year = year
vehicle.save(failOnError:true)
}
vehicle
}
// end::update[]
// tag::delete[]
abstract Vehicle delete(Serializable id)
// end::delete[]
}
This does not give the desired result. It creates the following runtime error:
How do I fix this error and establish the correct relationship? What underlying concept am I missing here? I know its SQL under the hood, but why doesn't joining the column work?
Wouldn't the generated query be something like:
SELECT * FROM Vehicles
JOIN Engines
WHERE Vehicles.ID = WHATEVER
ON Vehicles.engine_id= Engines.id
In grails-app/views/vehicle/create.gsp replace line 30:
<f:all bean="vehicle"/>
with
${example.Vehicle.withNewSession { session ->
f.all([bean: 'vehicle'])
}}
The error should go away.
Better solution:
replace line 30:
<f:all bean="vehicle"/>
with
<f:field bean="vehicle" property="model"/>
<f:field bean="vehicle" property="year"/>
You'll need to either mark engine as nullable and build another interface for it or add it to the form and add some binding code to the save action in VehicleController.