2
votes

I am currently working on an enterprise-architecture-management-system for my bachelor thesis in a insurance company. The company wants to display all self-made applications (Application-Node) in a Neo4J-Graphdatabase with Webservice-dependencies as relationships. Alongside the applications, the company also wants to persist the [Maven] versions (Version-Node) of an application (HAS_VERSION-Relationship), because new versions can have new dependencies or lose old ones (USES-Relationship). And here is my point. I want to provide unique Version-subnodes for each application instance. Such as:

APPLICATION Foo HAS_VERSION 1.0; 1.1; 2.0 and APPLICATION Bar HAS_VERSION 1.0; 2.0; 3.0; But the Version nodes 1.0 and 2.0 for both applications should be seperate nodes. So this example should display altogether 8 nodes (2 applications and 6 versions) in the graphdatabase. Is their a straightforward way to implement this with spring-data-neo4j? I already tried to use the @Unique annotation on the Version-Set in my Application POJO-Class. But this results in unique nodes for each version. So the example above displays 6 nodes (2 applications and 4 versions) in the database. And both applications have HAS_VERSION-relationships to the version nodes 1.0, 2.0. But I want explictly unique Version-"subnodes" for each application, because a USES-relationship to a version of an depending application should be directly visible in the database. With the unique Version-node it is not.

I also implemented a self-made way to do this. But it wasn't very efficient, because i do use many write and read-operations on the database. And some applications have many versions. So the @Fetch annotation is very resource-wasting. And now I am curious if spring-data-neo4j already provides a solution for my problem. Is their something to solve this efficiently?

1

1 Answers

1
votes

Yes, here's an example with Spring Data Neo4j 4 (currently in version M1). Note how you can control the persistence horizon or "depth" so be able to control fetching of related entities.

Application.java

@NodeEntity
public class Application {

    Long id;
    String name;
    @Relationship(type="HAS_VERSION", direction = "OUTGOING")
    Set<Version> versions = new HashSet<>();

    public Application() {
    }

    public Application(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void addVersion(Version version) {
        versions.add(version);
    }

    public Set<Version> getVersions() {
        return versions;
    }

    public Long getId() {
        return id;
    }
}

Version.java

@NodeEntity
public class Version {

    Long id;

    String versionNumber;

    @Relationship(type = "HAS_VERSION", direction = "INCOMING")
    Application application;


    public Version() {
    }

    public Version(String versionNumber) {
        this.versionNumber = versionNumber;
    }

    public String getVersionNumber() {
        return versionNumber;
    }

    public void setVersionNumber(String versionNumber) {
        this.versionNumber = versionNumber;
    }

    public Application getApplication() {
        return application;
    }

    public void setApplication(Application application) {
        this.application = application;
    }

    public Long getId() {
        return id;
    }
}

Repositories

public interface VersionRepository extends GraphRepository<Version> {

}

public interface ApplicationRepository extends GraphRepository<Application>{

}

And a test:

     @Test
                public void testDomain() {
                    Application foo = new Application("Foo");
                    Version foo10 = new Version("1.0"); //create a NEW version
                    Version foo11 = new Version("1.1"); //create a NEW version
                    Version foo20 = new Version("2.0"); //create a NEW version
                    foo.addVersion(foo10);
                    foo.addVersion(foo11);
                    foo.addVersion(foo20);
                    applicationRepository.save(foo);

                    Application bar = new Application("Bar");
                    Version bar10 = new Version("1.0"); //create a NEW version
                    Version bar20 = new Version("2.0"); //create a NEW version
                    Version bar30 = new Version("3.0"); //create a NEW version
                    bar.addVersion(bar10);
                    bar.addVersion(bar20);
                    bar.addVersion(bar30);
                    applicationRepository.save(bar);

                    session.clear();

                    assertEquals(2, applicationRepository.count()); //2 apps
                    assertEquals(6, versionRepository.count()); //6 versions

                    session.clear();

                    Application barWithoutVersionsLoaded = 
applicationRepository.findOne(bar.getId(),0); 

       //Depth=0 will only load the application and properties on the application node 
       //but not its related objects. 
       //If you don't specify depth, it defaults to 1
                    assertEquals("Bar", barWithoutVersionsLoaded.getName());
                    assertEquals(0, barWithoutVersionsLoaded.getVersions().size()); //No versions loaded

                }