Zusammenfassung Ein Elternteil kann viele Kinder haben. Wie schreiben Sie einen Dienst, bei dem nach dem Hinzufügen eines Elternelements beim Hinzufügen eines untergeordneten Objekts ein Fehler auftritt, wird die gesamte Transaktion zurückgesetzt. Fügen Sie beispielsweise übergeordnete p1 hinzu, fügen Sie erfolgreich untergeordnete c1 hinzu, und fügen Sie dann unter c2 einen Fehler ein, sollten sowohl p1 als auch c1 zurückgesetzt werden.So machen Sie Transaktionen in Grails
Detaillierte Problem
Im folgenden Code gibt es eine eindeutige Einschränkung auf den Namen des Vermögens des Kindes. Wenn Sie also versuchen, denselben Namen zweimal mit einem anderen übergeordneten Element hinzuzufügen, sollte der untergeordnete Datensatz nicht hinzugefügt und der übergeordnete Datensatz zurückgesetzt werden.
Mein Problem ist, dass der übergeordnete Datensatz nicht zurückgesetzt wird.
Ich verwende MySQL w/InnoDB mit Grails 1.2-M2 und Tomcat 6.018.
Datenquelle
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration
dataSource {
configClass = GrailsAnnotationConfiguration.class
pooled = true
driverClassName = "com.mysql.jdbc.Driver"
dialect = org.hibernate.dialect.MySQLInnoDBDialect
zeroDateTimeBehavior="convertToNull" //Java can't convert ''0000-00-00 00:00:00' to TIMESTAMP
username = "root"
password = "12345"
loggingSql=false
}
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider'
}
// environment specific settings
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
url = "jdbc:mysql://localhost:3306/transtest?zeroDateTimeBehavior=convertToNull"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:mysql://localhost:3306/transtest?zeroDateTimeBehavior=convertToNull"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:mysql://localhost:3306/transtest?zeroDateTimeBehavior=convertToNull"
}
}
}
Ich habe die folgenden einfachen Domain-Klassen:
Eltern:
class Parent {
static hasMany = [ children : Child ]
String name
static constraints = {
name(blank:false,unique:true)
}
}
Kinder
class Child {
static belongsTo = Parent
String name
Parent parent
static constraints = {
name(blank:false,unique:true)
}
}
Einfache Dateneingabe GSP
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sample title</title>
</head>
<body>
<h1>Add A Record</h1>
<g:form action="add" name="doAdd">
<table>
<tr>
<td>
Parent Name
</td>
<td>
Child Name
</td>
</tr>
<tr>
<td>
<g:textField name="parentName" />
</td>
<td>
<g:textField name="childName" />
</td>
</tr>
<tr><td><g:submitButton name="update" value="Update" /></td></tr>
</table>
</g:form>
</body>
</html>
-Controller
class AddrecordController {
def addRecordsService
def index = {
redirect action:"show", params:params
}
def add = {
println "do add"
addRecordsService.addAll(params)
redirect action:"show", params:params
}
def show = {}
}
Dienst
class AddRecordsService {
// boolean transactional = true //shouldn't this be all I need?
static transactional = true // this should work but still doesn't nor does it work if the line is left out completely
def addAll(params) {
println "add all"
println params
def Parent theParent = addParent(params.parentName)
def Child theChild = addChild(params.childName,theParent)
println theParent
println theChild
}
def addParent(pName) {
println "add parent: ${pName}"
def theParent = new Parent(name:pName)
theParent.save()
return theParent
}
def addChild(cName,Parent theParent) {
println "add child: ${cName}"
def theChild = new Child(name:cName,parent:theParent)
theChild.save()
return theChild
}
}
Danke für das Hinzufügen dieser wichtigen Details. –
> Sie müssen auch sicherstellen, dass eine RuntimeException innerhalb des > Dienstes ausgelöst wird, damit die Transaktion automatisch gerollt wird > zurück. Das war mein Problem! Sieht so aus, als würden die Grals dies per Konvention tun. –
Ich denke, es gibt eine Konfigurationsoption, Version 1.2 zu kommen, um save() auszulösen, anstatt Null zurückzugeben, wenn die Validierung fehlschlägt – leebutts