#NodeEntity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Employee {
#GraphId
private Long graphId;
#Indexed
private Long id;
private String name;
private String password;
#RelatedTo(type = "REPORT_TO", direction = Direction.OUTGOING)
private Department department;
}
I know spring-data-neo4j can use #Fetch to get Department data when get Employee entity, but not every time I need Department when get Employee, so how can I fetching department manully? The #Fetch annotation is not flexible
You can use Neo4jTemplate#fetch (T) to do manually what #Fetch does automagically.
See api doc here.
Related
I'm trying to map those three entities to each other without adding any additional fields to any of them. They should only contain the fields that already exist. I'm also trying to only get columns in the tables that represent the currently existing entity fields- and no additional columns.
#Entity
public class Order {
#Id
private Integer orderId;
private String title;
private Customer customer;
private List<Comment> comments;
}
#Entity
public class Customer {
#Id
private Integer customerId;
private String name;
}
#Entity
public class Comment {
#Id
private Integer commentId;
private Integer orderId;
private String details;
}
My understanding is that I can't simply use #OneToOne, #OneToMany and #ManyToOne mappings, because neither Customer nor Comment has a reference to Order . I'm trying to somehow reference the ids of Customer and Comment directly from Order.
I've tried using #MapsId and #JoinColumn but either I don't know how to properly use them, or they don't do what I think they do.
Is this task at all possible? If so, how to map them to each other?
For the reference to Comment you must use #JoinColum
The Customer reference assumes that there is a customer_id on the order table.
#Entity
public class Order {
#Id
private Integer orderId;
private String title;
#ManyToOne
#JoinColumn(name = "customer_id")
private Customer customer;
#OneToMany
#JoinColumn(name = "comment_id")
private List<Comment> comments;
}
I am trying to save a JPA entity which has ManytoMany Relationship (Consumer and Product table) and OnetoOne relation with ConsumerDetailstable.Below are my entities
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class)
#Entity
public class Consumer {
#Id
#GeneratedValue
private Long id;
private String firstName;
private String lastName;
#JsonManagedReference
#OnToMany(mappedBy = "consumer")
private Set<ConsumerProduct> consumerProducts;
#OneToOne
private CustomerDetails consumerDetails;
}
#Entity
public class Product {
#Id
#GeneratedValue
private Long productId;
private String productCode;
#OneToMany(mappedBy = "product")
private Set<ConsumerProduct> consumerProducts;
}
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class)
#Entity(the join table)
public class ConsumerProduct {
#EmbeddedId
ConsumerProductKey id;
#JsonBackReference
#ManyToOne
#MapsId("id")
#JoinColumn(name = "id")
private Consumer consumer;
#ManyToOne
#MapsId("productId")
#JoinColumn(name = "product_id")
private Product product;
}
#Embeddable (forgein keys combined as embeded id)
public class ConsumerProductKey implements Serializable {
#Column(name="id")
private Long id;
#Column(name = "product_id")
private Long productId;
}
#Enitity (one to one relation table)
public class CustomerDetails {
#Id
#GeneratedValue
private Long consumerDtlId;
#OneToOne
private Consumer consumer;
private String city;
private String state;
private String country;
}
To save the entity am have just extended JPARepository and called save method
public class ConsumerRepository<Consumer> Implements JPARepository<Consumer, Long> {
#Override
public Consumer S save(Consumer entity) {
return save(entity);
};
}
I get java.lang.StackOverFlowError at save method.
Anything wrong with my Mappings ?
Question: Since this will be save operation and since Consumer Id is yet to be generated how do I assign to below Entities
ConsumerProduct.ConsumerProductKey (how do i assign Id of consumer table once it is inserted to join table ? will JPA take care of it)
CustomerDetails (how do i assign Id of consumer table once it is inserted to join table ? will JPA take care of it)
EDIT: I have updated the entity with JsonManagedReference and JsonBackedReference but still i have am facing stackoverflow error
It is due to Consumer trying to access ConsumerProduct and ConsumerProduct trying to access consumer entity and end up with StackOverflow error.
You should use #JsonManagedReference and #JsonBackReference annotation in consumer and ConsumerProduct respectivly.
For sure, a simple question but I can't find my answer.
How can i get the entities from relationships using Neo4JRepository ?
Java 8 // Spring Boot 2 // SDN 5.0.9 // OGM 3
There is my code:
#NodeEntity(label = "category")
public class Category {
private #Id #GeneratedValue(strategy = InternalIdStrategy.class) Long id;
private String name;
#Relationship(type = "MEMBER_OF", direction = Relationship.INCOMING)
private Set<Sport> sports;
}
#NodeEntity(label = "sport")
public class Sport {
private #Id #GeneratedValue(strategy = InternalIdStrategy.class) Long id;
private String name;
private String descrition;
#Relationship(type = "MEMBER_OF")
private Set<Category> categories;
}
#RelationshipEntity(type = "MEMBER_OF")
public class Membership {
#Id
#GeneratedValue
private Long id;
#StartNode
Sport sport;
#EndNode
Category category;
}
A simple findAll from my Neo4jRepository return all nodes Sport but the set categories is null
So, can you tell me what did I wrong ?
Thanks.
Edit 21/08/2018
I changed my classes like this:
#NodeEntity(label = "sport")
public class Sport {
private #Id #GeneratedValue(strategy = InternalIdStrategy.class) Long id;
private String name;
private String descrition;
private Set<Membership> memberships;
}
#NodeEntity(label = "category")
public class Category {
private #Id #GeneratedValue(strategy = InternalIdStrategy.class) Long id;
private String name;
private Set<Membership> memberships;
}
#RelationshipEntity(type = "MEMBER_OF")
public class Membership {
#Id
#GeneratedValue
private Long id;
#StartNode
Sport sport;
#EndNode
Category category;
}
Now i've got this result:
In neo4j browser, the relationship is called merberships. Why OGM didn't use the RelationshipEntity's type ?
In my Rest service, using findAll, i still get null on this set.
Nope, it's ok here :) I've just forgot to keep #Relationship on my nodes
Another Question: How do I work with this Optional given by Neo4jRepository.findById, did someone have a good article for me ?
You are declaring a direct relationship between Category and Sport called MEMBER_OF but also define a rich relationship (#RelationshipEntity) with the same name.
Neo4j-OGM does not know what to map in this case.
From what I see in the sample code it is not necessary to add the rich relationship class at all because there are no additional properties defined and this would be the only reason to create such a class.
If you have properties defined but just not listed in the example, you should change the type of your collections and set it to Membership in both classes.
I am trying to integrate Javers with a Spring Data REST project. Currently I have the following entities in my domain.
Student.class
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private Long dob;
#OneToOne
private Gender gender;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "student", orphanRemoval = true)
private List<ContactNumber> contactNumbers = new ArrayList<>();
}
ContactNumber.class
#Entity
public class ContactNumber {
#Id
#GeneratedValue
private Long id;
private String phoneNumber;
private Boolean isPrimary;
#ManyToOne
private Student student;
}
In the javers docs it is mentioned that:
In the real world, domain objects often contain various kind of noisy
properties you don’t want to audit, such as dynamic proxies (like
Hibernate lazy loading proxies), duplicated data, technical flags,
auto-generated data and so on.
So does that mean I put a #DiffIgnore on the #ManyToOne student field in the contact number class or the #OneToMany contacts field in the student class?
It depends how you're logging the objects and what you want to log. Consider these two lines (suppose that you have a link between p and contactNumber)
//This logs p and contactNumber as part of the array part of p. If you want to ignore contactNumber here,
//add #DiffIgnore on the #OneToMany property. If you want to ignore
javers.commit("some_user", p);
//This would log contactNumber and p as the student. You can add #DiffIgnore here on the student property (#ManyToOne)
javers.commit("some_user", contactNumber);
Note that there is another annotation #ShallowReference that will log the id of the object instead of logging the entire object. E.g. if you add #ShallowReference to the student property it will not log the entire Person object, but only its ID. You can use that instead to have a link between those objects.
UPDATE:
Looking at your model, I'd recommend that you remove the student property. It doesn't make sense to have a link to the student from the phone number. The student has a number assigned, not the other way around. Thus your model would look like this.
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private Long dob;
#OneToOne
private Gender gender;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "student", orphanRemoval = true)
private List<ContactNumber> contactNumbers = new ArrayList<>();
}
ContactNumber.class
#Entity
public class ContactNumber {
#Id
#GeneratedValue
private Long id;
private String phoneNumber;
private Boolean isPrimary;
}
If you really need to find a Person/Student starting with a phone number you can have a Repository for your Person class that enables you to do that search. That would look like this:
//extend from the corresponding Spring Data repository interface based on what you're using. I'll use JPA for this example.
interface PersonRepository extends JpaRepository<Person, Long> {
Person findByPhoneNumber(String phoneNumber);
}
With this, your model is cleaner and you don't need to use DiffIgnore at all.
OK, so I've designed a basic CRUD an an exercise. It has 2 tables Jobs and Employees. I'm trying to create a many to one relationship, but when I click the link to go to the Employee Entry page it throws an error that kicks off with the #ManyToOne referencing an Unknown Entity.
Here is what I've got in my Employees.java
String jobName;
#ManyToOne(fetch=FetchType.EAGER)
#Fetch(value = FetchMode.JOIN)
#JoinColumn(name = "Job_Name")
#Column (name='jobName')
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
Any idea what i"m doing wrong and how to resolve this?
As per your comment,i think you can define relationship between these two entities like below.
#Entity
#Table(name="employee")
class Employee{
#Id
#GeneratedValue
private Integer id;
#ManyToOne
#JoinColumn(name = "job_name")
private Job job;
// other column and getter and setter
}
#Entity
#Table(name="job")
class Job{
#Id
#GeneratedValue
private Integer id;
#Column(name="job_name")
private String jobName;
//provide other column and getter setter
}