Re: Cross data map relationships
Andrus Adamchik <[email protected]> Tue, 14 Oct 2025 17:53:37 -0400
| Newsgroups | gmane.comp.java.cayenne.user |
|---|---|
| Message-ID | <[email protected]> |
See my follow up email :)=20 > On Oct 14, 2025, at 5:51=E2=80=AFPM, Ricardo Parada = <[email protected]> wrote: >=20 > Andrus, >=20 > What should I do then with the entity resolver? >=20 > I created it like you said but it=E2=80=99s still not being used. >=20 > Thank you > Ricardo Parada >=20 >=20 >=20 >=20 >> On Oct 14, 2025, at 5:33=E2=80=AFPM, Andrus Adamchik = <[email protected]> wrote: >>=20 >> =EF=BB=BF >>>=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