Monday, 15 November 2021

Spring Data: ArangoDB: Working with relations

You can define the relationship between entities using @Relations annotation.

 

For example, an employee can work on zero or more projects.

 

 


As shown in the above image,

a.   One employee can work in zero or more projects

b.   A project can be delivered by one or more employees

 

There is a many to many relationship here. To model this kind of relationship, we should create 2 document collections (employees, projects) and one edge collection (workingIn).

 

Entity classes

@Document("employees")
public class Employee {

	@Id // db document field: _key
	private String key;

	@ArangoId // db document field: _id
	private String arangoId;

	private Integer id;
	private String firstName;
	private String lastName;
	private Integer age;
	....
	....
}

@Document("projects")
public class Project {
	@Id // db document field: _key
	private String key;

	@ArangoId // db document field: _id
	private String arangoId;

	private Integer pjtId;

	private String projectName;

	....
	....
}

@Edge("workingIn")
public class WorkingIn {

	@Id // db document field: _key
	private String id;

	@ArangoId // db document field: _id
	private String arangoId;

	@From
	private Employee emp;

	@To
	private Project pjt;

	.....
	.....
}

Map the relationship between employee and project using edge collection workingIn

@Document("employees")
public class Employee {
	......
	......

	@Relations(edges = WorkingIn.class, lazy = true)
	private Collection<Project> projects;

	......
	......
}

@Document("projects")
public class Project {
	......
	......

	@Relations(edges = WorkingIn.class, lazy = true)
	private Collection<Employee> employees;

	......
	......
}

Find the below working application.

 

Step 1: Create new maven project ‘relations-demo’.

 

Step 2: Update pom.xml with maven dependencies.

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.sample.app</groupId>
	<artifactId>relations-demo</artifactId>
	<version>1</version>

	<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.5</version>
	</parent>


	<dependencies>
		<dependency>
			<groupId>com.arangodb</groupId>
			<artifactId>arangodb-spring-boot-starter</artifactId>
			<version>2.3.3.RELEASE</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Step 3: Define entity classes.

 

Employee.java

package com.sample.app.entity;

import java.util.Collection;

import org.springframework.data.annotation.Id;

import com.arangodb.springframework.annotation.ArangoId;
import com.arangodb.springframework.annotation.Document;
import com.arangodb.springframework.annotation.Relations;

@Document("employees")
public class Employee {

	@Id // db document field: _key
	private String key;

	@ArangoId // db document field: _id
	private String arangoId;

	private Integer id;
	private String firstName;
	private String lastName;
	private Integer age;

	@Relations(edges = WorkingIn.class, lazy = true)
	private Collection<Project> projects;

	public Employee() {

	}

	public Employee(Integer id, String firstName, String lastName, Integer age) {
		super();
		this.id = id;
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getArangoId() {
		return arangoId;
	}

	public void setArangoId(String arangoId) {
		this.arangoId = arangoId;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public Collection<Project> getProjects() {
		return projects;
	}

	public void setProjects(Collection<Project> projects) {
		this.projects = projects;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + "]";
	}

}

Project.java

package com.sample.app.entity;

import java.util.Collection;

import org.springframework.data.annotation.Id;

import com.arangodb.springframework.annotation.ArangoId;
import com.arangodb.springframework.annotation.Document;
import com.arangodb.springframework.annotation.Relations;

@Document("projects")
public class Project {
	@Id // db document field: _key
	private String key;

	@ArangoId // db document field: _id
	private String arangoId;

	private Integer pjtId;

	private String projectName;

	@Relations(edges = WorkingIn.class, lazy = true)
	private Collection<Employee> employees;

	public Project(Integer pjtId, String projectName) {
		super();
		this.pjtId = pjtId;
		this.projectName = projectName;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getArangoId() {
		return arangoId;
	}

	public void setArangoId(String arangoId) {
		this.arangoId = arangoId;
	}

	public Integer getPjtId() {
		return pjtId;
	}

	public void setPjtId(Integer pjtId) {
		this.pjtId = pjtId;
	}

	public String getProjectName() {
		return projectName;
	}

	public void setProjectName(String projectName) {
		this.projectName = projectName;
	}

	public Collection<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(Collection<Employee> employees) {
		this.employees = employees;
	}

	@Override
	public String toString() {
		return "Project [key=" + key + ", arangoId=" + arangoId + ", pjtId=" + pjtId + ", projectName=" + projectName
				+ "]";
	}

}

WorkingIn.java

package com.sample.app.entity;

import org.springframework.data.annotation.Id;

import com.arangodb.springframework.annotation.ArangoId;
import com.arangodb.springframework.annotation.Edge;
import com.arangodb.springframework.annotation.From;
import com.arangodb.springframework.annotation.To;

@Edge("workingIn")
public class WorkingIn {

	@Id // db document field: _key
	private String id;

	@ArangoId // db document field: _id
	private String arangoId;

	@From
	private Employee emp;

	@To
	private Project pjt;

	public WorkingIn(Employee emp, Project pjt) {
		this.emp = emp;
		this.pjt = pjt;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getArangoId() {
		return arangoId;
	}

	public void setArangoId(String arangoId) {
		this.arangoId = arangoId;
	}

	public Employee getEmp() {
		return emp;
	}

	public void setEmp(Employee emp) {
		this.emp = emp;
	}

	public Project getPjt() {
		return pjt;
	}

	public void setPjt(Project pjt) {
		this.pjt = pjt;
	}

	@Override
	public String toString() {
		return "WorkingIn [id=" + id + ", arangoId=" + arangoId + ", emp=" + emp + ", pjt=" + pjt + "]";
	}

}

Step 4: Define repository interfaces.

 

EmployeeRepository.java

package com.sample.app.repository;

import com.arangodb.springframework.repository.ArangoRepository;
import com.sample.app.entity.Employee;

public interface EmployeeRepository extends ArangoRepository<Employee, String> {


}

ProjectRepository.java

package com.sample.app.repository;

import com.arangodb.springframework.repository.ArangoRepository;
import com.sample.app.entity.Project;

public interface ProjectRepository extends ArangoRepository<Project, String> {

}

WorkingInRepository.java

package com.sample.app.repository;

import com.arangodb.springframework.repository.ArangoRepository;
import com.sample.app.entity.WorkingIn;

public interface WorkingInRepository extends ArangoRepository<WorkingIn, String>{

}

 

Step 5: Define ArangoDB configuration class.

 

ArangoConfig.java

package com.sample.app.config;

import org.springframework.context.annotation.Configuration;

import com.arangodb.ArangoDB;
import com.arangodb.springframework.annotation.EnableArangoRepositories;
import com.arangodb.springframework.config.ArangoConfiguration;

@Configuration
@EnableArangoRepositories(basePackages = { "com.sample.app" })
public class ArangoConfig implements ArangoConfiguration {

	@Override
	public ArangoDB.Builder arango() {
		return new ArangoDB.Builder().host("localhost", 8529).user("root").password("tiger");
	}

	@Override
	public String database() {
		return "abc_org";
	}
}

 

Step 6: Define main application class.

 

App.java

package com.sample.app;

import java.util.Collection;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.sample.app.entity.Employee;
import com.sample.app.entity.Project;
import com.sample.app.entity.WorkingIn;
import com.sample.app.repository.EmployeeRepository;
import com.sample.app.repository.ProjectRepository;
import com.sample.app.repository.WorkingInRepository;

@SpringBootApplication
public class App {
	public static void main(String args[]) {
		SpringApplication.run(App.class, args);
	}

	@Bean
	public CommandLineRunner demo(EmployeeRepository employeeRepo, ProjectRepository projectRepo,
			WorkingInRepository workingInRepository) {

		return (args) -> {

			Project pjt1 = new Project(1, "HPHS");
			Project pjt2 = new Project(2, "Employee management system");
			Project pjt3 = new Project(3, "Flight control system");

			pjt1 = projectRepo.save(pjt1);
			pjt2 = projectRepo.save(pjt2);
			pjt3 = projectRepo.save(pjt3);

			Employee emp1 = new Employee(1, "Ram", "Gurram", 31);
			Employee emp2 = new Employee(2, "Rudra", "Gurram", 32);
			Employee emp3 = new Employee(3, "Gopi", "Battu", 31);
			Employee emp4 = new Employee(4, "Joel", "Chelli", 32);
			Employee emp5 = new Employee(5, "Sailu", "Ptr", 31);
			Employee emp6 = new Employee(6, "Lahari", "Gurram", 23);

			emp1 = employeeRepo.save(emp1);
			emp2 = employeeRepo.save(emp2);
			emp3 = employeeRepo.save(emp3);
			emp4 = employeeRepo.save(emp4);
			emp5 = employeeRepo.save(emp5);
			emp6 = employeeRepo.save(emp6);

			WorkingIn workingInd1 = new WorkingIn(emp1, pjt1);
			WorkingIn workingInd2 = new WorkingIn(emp1, pjt2);
			WorkingIn workingInd3 = new WorkingIn(emp2, pjt1);
			WorkingIn workingInd4 = new WorkingIn(emp3, pjt3);
			WorkingIn workingInd5 = new WorkingIn(emp4, pjt3);
			WorkingIn workingInd6 = new WorkingIn(emp5, pjt1);

			workingInRepository.save(workingInd1);
			workingInRepository.save(workingInd2);
			workingInRepository.save(workingInd3);
			workingInRepository.save(workingInd4);
			workingInRepository.save(workingInd5);
			workingInRepository.save(workingInd6);

			Iterable<Employee> empsIterable = employeeRepo.findAll();

			System.out.println("Employees and the projects they are working in\n");
			for (Employee emp : empsIterable) {

				System.out.println("(" + emp.getFirstName() + "," + emp.getLastName() + ") is working in");
				Collection<Project> pjts = emp.getProjects();

				if (pjts == null || pjts.isEmpty()) {
					System.out.println("\tNot working in any project");
				} else {
					for (Project pjt : pjts) {
						System.out.println("\t" + pjt.getProjectName());
					}
				}

			}

			System.out.println("\n\nProjects and the employees working in\n");
			Iterable<Project> pjtsIterable = projectRepo.findAll();

			for (Project pjt : pjtsIterable) {
				System.out.println("Employees working in the project : " + pjt.getProjectName());

				for (Employee emp : pjt.getEmployees()) {
					System.out.println("\t(" + emp.getFirstName() + "," + emp.getLastName() + ")");
				}
			}

		};
	}
}

Total project structure looks like below.

 


Run App.java, you will see below messages in console.

Employees and the projects they are working in

(Ram,Gurram) is working in
	Employee management system
	HPHS
(Rudra,Gurram) is working in
	HPHS
(Gopi,Battu) is working in
	Flight control system
(Joel,Chelli) is working in
	Flight control system
(Sailu,Ptr) is working in
	HPHS
(Lahari,Gurram) is working in
	Not working in any project


Projects and the employees working in

Employees working in the project : HPHS
	(Sailu,Ptr)
	(Rudra,Gurram)
	(Ram,Gurram)
Employees working in the project : Employee management system
	(Ram,Gurram)
Employees working in the project : Flight control system
	(Joel,Chelli)
	(Gopi,Battu)

Information from arangosh

 

employees collection

127.0.0.1:8529@abc_org> db.employees.toArray()
[ 
  { 
    "_key" : "16533", 
    "_id" : "employees/16533", 
    "_rev" : "_cTssBnW---", 
    "_class" : "com.sample.app.entity.Employee", 
    "age" : 31, 
    "firstName" : "Ram", 
    "id" : 1, 
    "lastName" : "Gurram" 
  }, 
  { 
    "_key" : "16536", 
    "_id" : "employees/16536", 
    "_rev" : "_cTssBnm---", 
    "_class" : "com.sample.app.entity.Employee", 
    "age" : 32, 
    "firstName" : "Rudra", 
    "id" : 2, 
    "lastName" : "Gurram" 
  }, 
  { 
    "_key" : "16539", 
    "_id" : "employees/16539", 
    "_rev" : "_cTssBn2---", 
    "_class" : "com.sample.app.entity.Employee", 
    "age" : 31, 
    "firstName" : "Gopi", 
    "id" : 3, 
    "lastName" : "Battu" 
  }, 
  { 
    "_key" : "16542", 
    "_id" : "employees/16542", 
    "_rev" : "_cTssBoC---", 
    "_class" : "com.sample.app.entity.Employee", 
    "age" : 32, 
    "firstName" : "Joel", 
    "id" : 4, 
    "lastName" : "Chelli" 
  }, 
  { 
    "_key" : "16545", 
    "_id" : "employees/16545", 
    "_rev" : "_cTssBoK---", 
    "_class" : "com.sample.app.entity.Employee", 
    "age" : 31, 
    "firstName" : "Sailu", 
    "id" : 5, 
    "lastName" : "Ptr" 
  }, 
  { 
    "_key" : "16548", 
    "_id" : "employees/16548", 
    "_rev" : "_cTssBoS---", 
    "_class" : "com.sample.app.entity.Employee", 
    "age" : 23, 
    "firstName" : "Lahari", 
    "id" : 6, 
    "lastName" : "Gurram" 
  } 
]

projects collection

127.0.0.1:8529@abc_org> db.projects.toArray()
[ 
  { 
    "_key" : "16519", 
    "_id" : "projects/16519", 
    "_rev" : "_cTssBlW---", 
    "_class" : "com.sample.app.entity.Project", 
    "pjtId" : 1, 
    "projectName" : "HPHS" 
  }, 
  { 
    "_key" : "16522", 
    "_id" : "projects/16522", 
    "_rev" : "_cTssBmW---", 
    "_class" : "com.sample.app.entity.Project", 
    "pjtId" : 2, 
    "projectName" : "Employee management system" 
  }, 
  { 
    "_key" : "16525", 
    "_id" : "projects/16525", 
    "_rev" : "_cTssBmi---", 
    "_class" : "com.sample.app.entity.Project", 
    "pjtId" : 3, 
    "projectName" : "Flight control system" 
  } 
]

workingIn collection

127.0.0.1:8529@abc_org> db.workingIn.toArray()
[ 
  { 
    "_key" : "16558", 
    "_id" : "workingIn/16558", 
    "_from" : "employees/16533", 
    "_to" : "projects/16519", 
    "_rev" : "_cTssBpO---", 
    "_class" : "com.sample.app.entity.WorkingIn" 
  }, 
  { 
    "_key" : "16563", 
    "_id" : "workingIn/16563", 
    "_from" : "employees/16533", 
    "_to" : "projects/16522", 
    "_rev" : "_cTssBpi---", 
    "_class" : "com.sample.app.entity.WorkingIn" 
  }, 
  { 
    "_key" : "16568", 
    "_id" : "workingIn/16568", 
    "_from" : "employees/16536", 
    "_to" : "projects/16519", 
    "_rev" : "_cTssBpu---", 
    "_class" : "com.sample.app.entity.WorkingIn" 
  }, 
  { 
    "_key" : "16573", 
    "_id" : "workingIn/16573", 
    "_from" : "employees/16539", 
    "_to" : "projects/16525", 
    "_rev" : "_cTssBp6---", 
    "_class" : "com.sample.app.entity.WorkingIn" 
  }, 
  { 
    "_key" : "16578", 
    "_id" : "workingIn/16578", 
    "_from" : "employees/16542", 
    "_to" : "projects/16525", 
    "_rev" : "_cTssBqG---", 
    "_class" : "com.sample.app.entity.WorkingIn" 
  }, 
  { 
    "_key" : "16583", 
    "_id" : "workingIn/16583", 
    "_from" : "employees/16545", 
    "_to" : "projects/16519", 
    "_rev" : "_cTssBqS---", 
    "_class" : "com.sample.app.entity.WorkingIn" 
  } 
]

You can download the complete working application from below link.

https://github.com/harikrishna553/springboot/tree/master/arangodb/relations-demo


Previous                                                    Next                                                    Home

No comments:

Post a Comment