EDIT: метод onload() изменен на afterLoad(): иначе объекты могут не передаваться должным образом на карту.
В настоящее время я использую некоторые классы доменов с множеством динамических и сложных свойств, которые мне нужно постоянно обновлять и обновлять.
Я сохраняю их в структуре карты для каждого класса, так как это упрощает обращение к моим контроллерам и т.д.
Однако, поскольку Grails, похоже, не может сохранять сложные типы свойств, такие как List и Map в БД, я использую следующий подход для достижения этого через объекты JSON String:
class ClassWithComplexProperties {
Map complexMapStructure //not persisted
String complexMapStructureAsJSON //updated and synched with map via onload,beforeInsert,beforeUpdate
static transients = ['complexMapStructure']
def afterLoad() { //was previously (wrong!): def onLoad() {
complexMapStructure=JSON.parse(complexMapStructureAsJSON)
}
def beforeInsert() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
def beforeUpdate() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
static constraints = {
complexMapStructureAsJSON( maxSize:20000)
}
}
Это работает так долго, что я только загружаю данные из БД, но у меня возникают проблемы, когда я хочу сохранить свои изменения в БД. Например. когда я делаю следующее
/* 1. Load the json String, e.g. complexMapStructureAsJSON="""{
data1:[[1,2],[3,4]],//A complex structure of nested integer lists
data1:[[5,6]] //Another one
}""" :
*/
ClassWithComplexProperties c=ClassWithComplexProperties.get(1)
// 2. Change a value deep in the map:
c.complexMapStructure.data1[0][0]=7
// 3. Try to save:
c.save(flush:true)
Это обычно не работает, поскольку, я думаю, (?), GORM игнорирует запрос save() из-за того, что сама карта является временной, и никаких изменений в сохраняемых свойствах не обнаружено.
Я могу заставить его работать по назначению, если я взломаю шаг 3 выше и изменил его на:
// 3.Alternative save:
complexMapStructureAsJSON="" //creating a change in persisted property (which will be overwritten anyway by the beforeUpdate closure)
c.save(flush:true)
Для меня это не очень элегантное решение моей проблемы. Вопросы:
- Существует ли более простой подход к сохранению моих сложных данных динамической карты?
- Если мне нужно сделать это так, как я сейчас делаю, есть ли способ избежать взлома на шаге 3?