Hi,
I encounter some strange behaviour where Glorp
actually updates instead of doing inserts. I am
still on my export import capabilities of my application. Actually I choose to
rebuild my network from. scratch or have the ability to add the contents to an
existing one (storing old id's and new ones in a dictionary to do the
housekeeping). The enclosed method does this for a simple Hierarchy node of a
treeView in my GUI (I marked where things go wrong). The treeView expect
the root to have an id = 1 and the method will not add a node if one with the
same name allready exists.
readAndRegisterFromStreamOrganisationTreeNode:
srs
| aClassAssociation aClassStructure newItem
oldID existingNode newRootName |
aClassAssociation := srs next. aClassAssociation value isNil ifFalse: [importDic add: #OrganisationTreeNode -> Dictionary new. aClassAssociation value timesRepeat: [aClassStructure := srs next. OrganisationTreeNode = aClassStructure key ifTrue: [newItem := self importReconstructFrom: aClassStructure. oldID := newItem id. newItem id = 1 ifTrue: [self getGlorpSession inUnitOfWorkDo: [existingNode := self getGlorpSession readOneOf: OrganisationTreeNode where: [:each | each id = 1]. existingNode isNil ifTrue: [self getGlorpSession inUnitOfWorkDo: [self getGlorpSession register: newItem]] ifFalse: [existingNode name = newItem name ifFalse: [newRootName := Dialog choose: 'Select organisation existingNode name' labels: (Array with: existingNode name with: newItem name) values: (Array with: existingNode name with: newItem name) default: existingNode name. existingNode name: newRootName]]]] ifFalse: [newItem id: nil. existingNode := self getGlorpSession readOneOf: OrganisationTreeNode where: [:each | each name = newItem name]. existingNode isNil ifTrue: [Transcript show:'Justed Counted existing nodes =', (self getGlorpSession count: OrganisationTreeNode) printString;cr. self getGlorpSession reset. "If I reset the session here it provokes the enclosed stack trace, if not it updates newItem with id =1 see Log" self getGlorpSession inUnitOfWorkDo: [self getGlorpSession register: newItem]] ifFalse: [newItem := existingNode]]. (importDic at: #OrganisationTreeNode) add: oldID -> Dictionary new. ((importDic at: #OrganisationTreeNode) at: oldID) at: #id put: newItem id]]]. The trancript lgging is as follows from the
beginnning of the method:
As you can see it first inserts the root node
'Organisation" then it updates instead of inserting.
SELECT t1.id, t1.name, t1.shortname FROM MMT_ORGANISATION_TREE_NODE t1 WHERE (t1.id = 1) (0.015 s) Begin Transaction INSERT INTO MMT_ORGANISATION_TREE_NODE (id,name,shortname) VALUES (1,'Organisation',NULL) (0.006 s) Commit Transaction SELECT t1.id, t1.name, t1.shortname FROM MMT_ORGANISATION_TREE_NODE t1 WHERE (t1.name = 'hjhhhjhjhjhjhj') (0.013 s) SELECT COUNT(*) FROM MMT_ORGANISATION_TREE_NODE t1 (0.013 s)Justed Counted existing nodes =1 Begin Transaction
select MMT_ORGANISATION_TREE_NODE_id_.nextval from SYS.ALL_OBJECTS WHERE rownum <= 1 (0.082 s) UPDATE MMT_ORGANISATION_TREE_NODE SET name = 'hjhhhjhjhjhjhj',shortname = NULL WHERE id = 1 (0.004 s) Commit Transaction My Descriptor is as follows:
classModelForOrganisationTreeNode: aClassModel
aClassModel newAttributeNamed: #id. aClassModel newAttributeNamed: #children collectionOf: OrganisationTreeNode. aClassModel newAttributeNamed: #parent type: OrganisationTreeNode. aClassModel newAttributeNamed: #resourcecol collection: OrderedCollection of: Resource descriptorForOrganisationTreeNode: aDescriptor
| table | table := self tableNamed: 'MMT_ORGANISATION_TREE_NODE'. aDescriptor table: table. (aDescriptor newMapping: DirectMapping) from: #id to: (table fieldNamed: 'id'). (aDescriptor newMapping: DirectMapping) from: #name to: (table fieldNamed: 'name'). (aDescriptor newMapping: DirectMapping) from: #shortname to: (table fieldNamed: 'shortname'). (aDescriptor newMapping: Glorp.OneToOneMapping) attributeName: #parent; useLinkTable; join: (Glorp.Join from: (table fieldNamed: 'id') to: ((self tableNamed: 'MMT_ORGANISATION_TREE_LINK') fieldNamed: 'CHILD')). (aDescriptor newMapping: Glorp.ToManyMapping) attributeName: #children; useLinkTable; join: (Glorp.Join from: (table fieldNamed: 'id') to: ((self tableNamed: 'MMT_ORGANISATION_TREE_LINK') fieldNamed: 'PARENT')). (aDescriptor newMapping: Glorp.ToManyMapping) attributeName: #resourcecol; orderBy: #res_name tableForMMT_ORGANISATION_TREE_NODE: aTable
(aTable createFieldNamed: 'id' type: platform sequence) bePrimaryKey. aTable createFieldNamed: 'name' type: (platform varchar: 255). aTable createFieldNamed: 'shortname' type: (platform varchar: 60) Resetting the glorpSession should not
influence the transaction.
It does however with the following stack
trace:
Unhandled exception:
ORA-00001: violation de contrainte unique (MMT.MMT_ORGANISATION_TREE_NODE_PK) Glorp.GlorpDatabaseWriteError(Glorp.GlorpError)>>signal
Glorp.VWDatabaseAccessor(Glorp.DatabaseAccessor)>>handleError:for: optimized [] in [] in Glorp.DatabaseAccessor>>executeCommand:returnCursor: BlockClosure>>cull: IndexConflict(GenericException)>>performHandler: IndexConflict(GenericException)>>propagatePrivateFrom: IndexConflict(GenericException)>>propagateFrom: IndexConflict(GenericException)>>propagate IndexConflict(GenericException)>>raiseSignal IndexConflict class(GenericException class)>>raiseWith:errorString: OracleThreadedSession(OracleSession)>>resultsExternal OracleThreadedSession(OracleSession)>>executeExternal optimized [] in ExternalDatabaseSession>>execute BlockClosure>>ifCurtailed: OracleThreadedSession(ExternalDatabaseSession)>>execute Glorp.VWDatabaseAccessor>>basicExecuteSQLString:returnResult:binding:doing: Glorp.VWDatabaseAccessor>>basicExecuteSQLStringNoResult:doing: optimized [] in Glorp.DatabaseAccessor>>executeSQLStringNoResult:doing:forCommand: Time class>>microsecondsToRun: Time class>>millisecondsToRun: Glorp.VWDatabaseAccessor(Glorp.DatabaseAccessor)>>executeSQLStringNoResult:doing:forCommand: Glorp.InsertCommand(Glorp.RowBasedCommand)>>executeUnboundIn: optimized [] in [] in Glorp.DatabaseAccessor>>executeCommand:returnCursor: BlockClosure>>on:do: optimized [] in Glorp.DatabaseAccessor>>executeCommand:returnCursor: BlockClosure>>ensure: Semaphore>>critical: Glorp.VWDatabaseAccessor(Glorp.DatabaseAccessor)>>executeCommand:returnCursor: Glorp.VWDatabaseAccessor(Glorp.DatabaseAccessor)>>executeCommand: Glorp.GlorpSession>>groupWrite: Glorp.GlorpSession>>writeHomogeneousRows:from:to: Glorp.GlorpSession>>writeHomogeneousRows: optimized [] in Glorp.UnitOfWork>>writeRowsForTable: Dictionary>>do: Glorp.UnitOfWork>>writeRowsForTable: optimized [] in Glorp.UnitOfWork>>writeRows OrderedCollection>>do: Glorp.UnitOfWork>>writeRows optimized [] in Glorp.UnitOfWork>>commit BlockClosure>>ifCurtailed: Glorp.UnitOfWork>>commit optimized [] in [] in Glorp.GlorpSession>>commitUnitOfWork optimized [] in Glorp.DatabaseAccessor>>inTransactionDo: BlockClosure>>ifCurtailed: Glorp.VWDatabaseAccessor(Glorp.DatabaseAccessor)>>inTransactionDo: Glorp.GlorpSession>>inTransactionDo: optimized [] in Glorp.GlorpSession>>commitUnitOfWork BlockClosure>>ifCurtailed: Glorp.GlorpSession>>commitUnitOfWork optimized [] in Glorp.GlorpSession>>inUnitOfWorkDo: BlockClosure>>ifCurtailed: Glorp.GlorpSession>>inUnitOfWorkDo: MainProject(GlorpFrameWork)>>readAndRegisterFromStreamOrganisationTreeNode: optimized [] in GlorpFrameWork>>importDatabaseXML BlockClosure>>ensure: Cursor>>showWhile: MainProject(GlorpFrameWork)>>importDatabaseXML _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
This is not trivial to follow, and in particular it's not
obvious where newItem comes from. But basically, Glorp's algorithm for
whether it's inserting or updating is simple. If it read the object from
the database in the first place, then it's an update. Otherwise, it's an
insert. And the way it knows if it read it from the database or not is if
the cache contains that object. See
GlorpSession>>shouldInsert:
It will look up based on the primary key, and decide what to do based on that. So either that primary key corresponds to something you already read from the database, or it's confused about what the primary key fields are. It's probably the first, which is why you get an Oracle error if it tries to insert. You're trying to insert two different rows in the same table with the same primary key. The reason that's different if you reset the session is that if you reset, the cache is now empty, so the cache doesn't contain the object, so it's assumed to be an insert, rather than an update. At 03:58 PM 2010-01-19, Maarten MOSTERT wrote: Hi, --
Alan Knight [|], Engineering Manager, Cincom Smalltalk
_______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Free forum by Nabble | Edit this page |