Re: Cross data map relationships
Andrus Adamchik <[email protected]> Tue, 14 Oct 2025 17:39:19 -0400
| Newsgroups | gmane.comp.java.cayenne.user |
|---|---|
| Message-ID | <[email protected]> |
> EntityResolver namespace =3D new EntityResolver(List.of(mainMap, = errorsMap)); A small correction. Actually this should look a bit different for it to = have effect: EntityResolver namespace =3D new EntityResolver(); namespace.addDataMap(mainMap); namespace.addDataMap(errorsMap); (Sigh, I hate mutable objects and side effects =F0=9F=99=82 In Cayenne = 6, we should have constructor/builder-only initialization of all configs = and no set/add stuff). Andrus > On Oct 14, 2025, at 5:33=E2=80=AFPM, Andrus Adamchik = <[email protected]> wrote: >=20 >> I then save the first data map and it throws a NullPointerException. = =20 >=20 > Before save, try this to make sure entities can find each other across = DataMaps: >=20 > EntityResolver namespace =3D new EntityResolver(List.of(mainMap, = errorsMap)); >=20 >> (I avoided creating data nodes and the project in this code to keep = things simple and illustrate the NullPointerException) >=20 > BTW, if you have a single DataNode, don't bother creating it in the = model. It is much simpler and cleaner to just assign a DataSource when = creating a CayenneRuntime, and Cayenne will use it to handle all = DataMaps in the project. >=20 > Andrus >=20 >=20 >> On Oct 14, 2025, at 5:23=E2=80=AFPM, Ricardo Parada = <[email protected]> wrote: >>=20 >> Here is a very minimal test of what I am seeing. >>=20 >> Two data maps: Main and Errors. >>=20 >> I have an APP_USER DbTable in the Main data map and an APP_ERROR = DbTable in the Errors data map. >>=20 >> Then I have a to-many relationship and inverse to one between these = two. >>=20 >> APP_USER <->> APP_ERROR >>=20 >> I then simply create the ObjEntity, ObjAttribute and ObjRelationship = objects programmatically. >>=20 >> I then save the first data map and it throws a NullPointerException. = =20 >>=20 >> Here is the isolated test: >>=20 >> (I avoided creating data nodes and the project in this code to keep = things simple and illustrate the NullPointerException) >>=20 >> package play.cay.utils.conversion; >>=20 >> import java.io.PrintWriter; >> import java.sql.Types; >>=20 >> import = org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor; >> import org.apache.cayenne.map.DataMap; >> import org.apache.cayenne.map.DbAttribute; >> import org.apache.cayenne.map.DbEntity; >> import org.apache.cayenne.map.DbJoin; >> import org.apache.cayenne.map.DbRelationship; >> import org.apache.cayenne.map.ObjAttribute; >> import org.apache.cayenne.map.ObjEntity; >> import org.apache.cayenne.map.ObjRelationship; >> import org.apache.cayenne.util.XMLEncoder; >>=20 >> public class DataMapTest { >>=20 >> public static void main(String[] args) { >> // Create DataMaps >> DataMap mainMap =3D new DataMap("Main"); >> DataMap errorsMap =3D new DataMap("Errors"); >>=20 >> // -------------------- DB Entities -------------------- >>=20 >> // APP_USER DbEntity >> DbEntity appUserDb =3D new DbEntity("APP_USER"); >> DbAttribute appUserIdDbAttr =3D new DbAttribute("ID", = Types.INTEGER, appUserDb); >> appUserIdDbAttr.setPrimaryKey(true); >> appUserDb.addAttribute(appUserIdDbAttr); >> appUserDb.addAttribute(new DbAttribute("NAME", Types.VARCHAR, = appUserDb)); >> appUserDb.addAttribute(new DbAttribute("EMAIL", Types.VARCHAR, = appUserDb)); >> appUserDb.getPrimaryKeyGenerator(); >>=20 >> // APP_ERROR DbEntity >> DbEntity appErrorDb =3D new DbEntity("APP_ERROR"); >> DbAttribute appErrorIdDbAttr =3D new DbAttribute("ID", = Types.INTEGER, appErrorDb); >> appErrorDb.addAttribute(appErrorIdDbAttr); >> appErrorDb.addAttribute(new DbAttribute("APP_USER_ID", = Types.INTEGER, appErrorDb)); >> appErrorDb.addAttribute(new DbAttribute("ERROR_MESSAGE", = Types.VARCHAR, appErrorDb)); >>=20 >> // Add DbEntities to respective maps >> mainMap.addDbEntity(appUserDb); >> errorsMap.addDbEntity(appErrorDb); >>=20 >> // -------------------- DB Relationships -------------------- >>=20 >> // APP_ERROR -> APP_USER (to-one) >> DbRelationship toUserRel =3D new DbRelationship("appUser"); >> toUserRel.setSourceEntity(appErrorDb); >> toUserRel.setTargetEntityName(appUserDb); >> toUserRel.setToMany(false); >> toUserRel.addJoin(new DbJoin(toUserRel, "APP_USER_ID", "ID")); >> appErrorDb.addRelationship(toUserRel); >>=20 >> // APP_USER ->> APP_ERROR (to-many) >> DbRelationship errorsRel =3D new DbRelationship("errors"); >> errorsRel.setSourceEntity(appUserDb); >> errorsRel.setTargetEntityName(appErrorDb); >> errorsRel.setToMany(true); >> errorsRel.addJoin(new DbJoin(errorsRel, "ID", "APP_USER_ID")); >> appUserDb.addRelationship(errorsRel); >>=20 >> // -------------------- ObjEntities -------------------- >>=20 >> // APP_USER ObjEntity >> ObjEntity appUserObj =3D new ObjEntity("AppUser"); >> appUserObj.setDbEntity(appUserDb); >> appUserObj.addAttribute(new ObjAttribute("id", = "java.lang.Integer", appUserObj)); >> appUserObj.addAttribute(new ObjAttribute("name", = "java.lang.String", appUserObj)); >> appUserObj.addAttribute(new ObjAttribute("email", = "java.lang.String", appUserObj)); >>=20 >> // APP_ERROR ObjEntity >> ObjEntity appErrorObj =3D new ObjEntity("AppError"); >> appErrorObj.setDbEntity(appErrorDb); >> appErrorObj.addAttribute(new ObjAttribute("id", = "java.lang.Integer", appErrorObj)); >> appErrorObj.addAttribute(new ObjAttribute("errorMessage", = "java.lang.String", appErrorObj)); >>=20 >> // Add ObjEntities to respective maps >> mainMap.addObjEntity(appUserObj); >> errorsMap.addObjEntity(appErrorObj); >>=20 >> // -------------------- ObjRelationships -------------------- >>=20 >> // AppError =C3=A2=C2=86=C2=92 AppUser (to-one) >> ObjRelationship appUserRel =3D new ObjRelationship("appUser"); >> appUserRel.setSourceEntity(appErrorObj); >> appUserRel.setTargetEntityName(appUserObj); // sets target name >> appUserRel.setDbRelationshipPath("appUser"); >> appErrorObj.addRelationship(appUserRel); >>=20 >> // AppUser =C3=A2=C2=86=C2=92 AppError (to-many) >> ObjRelationship errorsRelObj =3D new ObjRelationship("errors"); >> errorsRelObj.setSourceEntity(appUserObj); >> errorsRelObj.setTargetEntityName(appErrorObj); // sets target = name >> errorsRelObj.setDbRelationshipPath("errors"); >> appUserObj.addRelationship(errorsRelObj); >>=20 >> PrintWriter stdout =3D new PrintWriter(System.out, true); >> XMLEncoder encoder =3D new XMLEncoder(stdout, "\t", "11"); >> EmptyConfigurationNodeVisitor visitor =3D new = EmptyConfigurationNodeVisitor(); >>=20 >> stdout.println(mainMap.getName()); >> stdout.println(); >> encoder.nested(mainMap, visitor); >>=20 >> stdout.println(); >> stdout.println(); >>=20 >> stdout.println(errorsMap.getName()); >> stdout.println(); >> encoder.nested(errorsMap, visitor); >>=20 >> } >> } >>=20 >>=20 >>=20 >>>=20 >>> On Oct 14, 2025, at 3:29=E2=80=AFPM, Ricardo Parada = <[email protected]> wrote: >>>=20 >>> =EF=BB=BFHello, >>>=20 >>> I wrote a converter to convert our eomodels from EOF to = Cayenne-project.xml and data maps .map.xml >>>=20 >>> So far so good. However, I seem to be running into a problem for = cross data map relationships. >>>=20 >>> I=E2=80=99m using 5.0-M1. >>>=20 >>> When I=E2=80=99m creating the ObjRelationship I call: >>>=20 >>> objRel.setTargetEntityName(targetObjEntity); >>>=20 >>> If I then call objRel.getTargetEntityName() it returns the correct = target entity name. =20 >>>=20 >>> However, if I call objRel.getTargetEntity() it returns null. >>>=20 >>> I debugged the code and I can see that getTargetEntity() is looking = for the target entity name in the data map corresponding to the source = ObjEntity. And it does not find it and returns null for that reason. >>>=20 >>> As a result of that, when I call encodeAsXML() on objRel I see that = the XML is missing the target attribute in the obj-relationship xml tag. >>>=20 >>> Is this a bug in 5.0-M1 or am I missing something when creating my = ObjRelationship programmatically. >>>=20 >>> I could put all eomodels that have cross eomodel relationships into = the same data map to avoid this problem. >>>=20 >>> But when I create it in Cayenne Modeler 4.3.3 it seems to work. I = see the obj-relationship in the XML have target correctly set. >>>=20 >>> Thank you all in advance. >>> Ricardo Parada >=20