There can be issues if you modify other objects inside lifecycle callbacks (a callback won't be called on that object). I would recommend doing the mods in validateForSave instead.
On Thu, Apr 4, 2019 at 6:44 AM Hugi Thordarson <[email protected]> wrote: > Yes, this would have been a good idea :). Unfortunately the model > (containing dozens of tables and hundreds of relationships) is already > completely modeled using relationships and makes heavy use of them (for > expressions, ordering, prefetching etc. etc.) > > The Cayenne-project was originally created as the reporting-part of the > system, so I didn't really hit these issues until now, when we're moving > the actual "write" part of the system there as well. > > Dang… > > Cheers, > - hugi > > > > > On 4 Apr 2019, at 11:10, Ken Anderson <[email protected]> wrote: > > > > My guess would be “no”. > > > > I suggest you don’t model the relationships until the foreign systems > are fixed or removed. In the meanwhile, I would implement methods as the > relationships, that would know if there’s a fictitious value or not and > return NULL for the relationship. When the other systems are fixed, remove > the method and implement the relationship normally. > > > >> On Apr 4, 2019, at 6:39 AM, Hugi Thordarson <[email protected]> wrote: > >> > >> I spoke a little too soon—my solution isn't sufficient, who'd have > thunk it :). > >> > >> Some of the columns with "fictional null values" are used in > relationships. For example, I can have an invoice with customer_id "-1" to > indicate that there's no related customer. > >> > >> As I'm done cleaning up the DB, these will eventually end up as actual > foreign keys with nulls instead of that -1, so I'd like to model the > relationship, hide the FK in the ObjEntity and use the "customer" > relationship (I've actually modeled it like that already and it works fine > for read operations, but of course everything explodes once I try to write > and object with a null customer to the DB and "customer_id" is set to null). > >> > >> So, I kind of need to be doing this on the DbEntity level (if customer > is null, write "-1" to the customer_id). > >> > >> Is this at all possible? > >> > >> Cheers, > >> - hugi > >> > >> > >>> On 4 Apr 2019, at 10:09, Hugi Thordarson <[email protected]> wrote: > >>> > >>> Hi all, > >>> I'm currently working on a legacy system. The DB has a lot of columns > where null should actually be allowed, but instead those fields are > non-nullable and get other values (empty string, "0", "-1" etc) written to > them to indicate the absence of a value. Yay. > >>> > >>> Unfortunately I can't just do the right thing; make the fields > nullable and start writing nulls, since that would make other (non Cayenne) > parts of the system explode, so I have to create a temporary workaround > while I work through each column and make it nullable and fix (or kill) the > legacy apps. > >>> > >>> What I'd like to do is write my application logic as if the column was > nullable, setting nulls when I want to, but when the object goes to the DB, > "legacy nulls" are written to the DB instead (empty string or "-1" or > whatever). > >>> > >>> I have a working solution, I just wanted to check if you guys would > have a better or more performant solution or see anything potentially wrong > with what I'm doing. > >>> > >>> What I'm doing is creating an interface (HasFictionalNullValues) which > can be implemented by entity classes that require it. It defines a single > method that can be implemented like… > >>> > >>> public class SomeEntityClass extends _SomeEntityClass implements > HasFictionalNullValues { > >>> > >>> @Override > >>> Map<Property,Object> fictionalNullValues) { > >>> Map<Property,Object map = new HashMap<>(); > >>> map.put( NAME, "" ); > >>> map.put( AGE, -1 ); > >>> return map; > >>> } > >>> > >>> [...rest of class body...] > >>> } > >>> > >>> …then I add a listener to my DataDomain to catch new and updated > objects > >>> > >>> public class FictionalNullValuesListener { > >>> > >>> @PrePersist( { BaseDataObject.class } ) > >>> @PreUpdate( { BaseDataObject.class } ) > >>> public void onPrePersist( BaseDataObject object ) { > >>> if( object instanceof HasFictionalNullValues ) { > >>> > ((HasFictionalNullValues)object).fictionalNullValues().forEach( ( > property, replacementNullValue ) -> { > >>> if( property.getFrom( object ) == null ) { > >>> property.setIn( object, > replacementNullValue ); > >>> } > >>> } ); > >>> } > >>> } > >>> } > >>> > >>> Any comments on this practice or something I'm missing? > >>> > >>> Cheers, > >>> - hugi > >> > > > >
