Deleting a Node and all of its relations in Neo4j - java

I am trying to delete all Type's from my Neo4j database. I have a repository for the Type class, typeRepository, which I call typeRepository.deleteAll();. However, not everything is deleted. Only its node is deleted leaving the BusinessLogic node alive in the database. I am not sure what else to try at this point, since it name of the method implies that it will delete all things including itself and things related to itself. Here is how my persisted class looks, which extends a base type of object that my database contains:
#NodeEntity
public class BaseType {
#GraphId
private Long id;
#Indexed(unique=true) String uid;
private String name;
BaseType() {}
BaseType(String name) {
this.name = name;
}
}
,
public class Type extends BaseType {
#RelatedTo(type="businessLogic")
#Fetch
private BusinessLogic businessLogic;
public Type() {super();}
public Type(String name, BusinessLogic businessLogic) {
super(name);
this.businessLogic = businessLogic;
}
}
,
#NodeEntity
#XmlAccessorType(XmlAccessType.NONE)
public class BusinessLogic implements Serializable {
#GraphId
private Long id;
private static final long serialVersionUID = -634875134095817304L;
#XmlElement
private String create;
public void setCreate(String create) {
this.create = create;
}
public String getCreate() {
return create;
}
}
I only store the Type instances, and I do that by calling
typeRepository.save(new Type(name, businessLogic));.

I don't think SDN is doing cascading delete on its own. So, why don't you first delete the BusinessLogic objects via their respective repository, and then the Type objects?

Related

Entity class defines non-transient non-serializable instance field price

Below little bit of code showing SONAR bug like :Class com.sample.Submit defines non-transient non-serializable instance field price. How can we get rid from this issue.
Code
#JsonIgnoreProperties(ignoreUnknown = true)
public class Submit implements Serializable {
/**
* serialVersionUID of type long.
*/
private static final long serialVersionUID = 0L;
#JsonProperty("billCode")
private String billCode;
#JsonProperty("displayName")
private String displayName;
#JsonProperty("visible")
private Boolean visible;
#JsonProperty("price")
private Price price;
public Boolean getVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
public String getBillCode() {
return billCode;
}
public void setBillCode(String billCode) {
this.billCode = billCode;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public Price getPrice() {
return price;
}
public void setPrice(Price price) {
this.price = price;
}
}
Declare your class Price serializable as follows:
public class Price implements Serializable {
...
}
If you actually need the class to be serializable, then every one of its instance members, like Price, needs to be serializable as well.
Consider if you actually need this Submit class to be serializable though. If you are not doing anything that requires storing this or copying it across a network (like putting it in the HTTP session, or saving it on a file system, or putting it in a queue), you may not need the class to be serializable at all, in which the best course to take is to delete the implements Serializable from the Submit class.
(Be aware that making the class serializable has nothing to do with using it to generate JSON.)

Neo4j OGM & Multiple similar classes

I'm using Neo4j ogm to map many (over 20) similar classes into neo4j db which are different in just
relationship name, name and direction.
Each class implements the "Classification" interface with just one method which is the same
in every class (consist on adding relation into collection of node)
Example node:
#NodeEntity
public class ExampleClass implements Classification {
#GraphId
private Long id;
private String name;
#Relationship(type = "EXAMPLE_1", direction = "OUTGOING")
private Set<Species> classification = new HashSet<>();
public ExampleClass (){}
public ExampleClass (String name) {
this.name = name;
}
public Set<Species> getClassification(){
return classification;
}
#Override
public void specifiedAs(Species species){
classification.add(species);
}
and analogously:
#NodeEntity
public class ExampleClass2 implements Classification {
#GraphId
private Long id;
private String name;
#Relationship(type = "EXAMPLE_2", direction = "OUTGOING")
private Set<Species> classification = new HashSet<>();
public ExampleClass2 (){}
public ExampleClass2 (String name) {
this.name = name;
}
public Set<Species> getClassification(){
return classification;
}
#Override
public void specifiedAs(Species species){
classification.add(species);
}
}
I'm looking for possibility to reduce count of those similar classes
and create... maybe one generic class in which I can define label,property name and realtionship type also.
I prefer still using spring-data and Neo4j OGM.
You could improve this by introducing an super class containing all the common properties, and just have the specific relationships in your ExampleClassXXX classes.
Note that the relationship types cannot be dynamic, so you cannot have just a generic class by itself.

How to get subclasses attributes using SingleTableInheritance with SpringMVC

i am working on a web application using Spring, Hibernate and SpringMVC,
i am facing a problem with retreiving values from a subclass table using SingleTable inheritance strategy, here are my entities
Client.java (Super class)
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "typeClient", discriminatorType = DiscriminatorType.STRING)
public class Client implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idClient;
private String matricule;
private String statut;
private String secteurDactivite;
private String nomClient;
private String emailClient;
private String numTelephone;
private String adresse;
//constructor
//getter & setters
}
Societe.java (subClass1)
#Entity
#DiscriminatorValue("Societe")
public class Societe extends Client implements Serializable{
private String nomResponsable;
private String emailResponsable;
private String telResponsable;
private String nomSuperieur;
private String emailSuperieur;
private String telSuperieur;
private String commentaire;
//constructeur sans parametre
public Societe() {
}
}
Particulier.java (subclass2)
#Entity
#DiscriminatorValue("Particulier")
public class Particulier extends Client implements Serializable {
private String cin;
//constructeur sans parametres
public Particulier() {
}
}
in my implementation i am using this methode to get a particular client with his ID
ClientDaoImpl.java
public class ClientDaoImpl implements ClientDao {
#PersistenceContext
private EntityManager em;
#Override
public Client getClientByID(int id_client) {
return em.find(Client.class, id_client);
}
When i ran this code i only selected the attributes of the superClass Client.
what i am trying to do is to get a client with its subclass whether it's a Societe or Particulier based on its type or clientID.
Please Help
As you don't know the type of client before querying and only it's ID, you will need to inspect the type and cast after you retrieve the record;
Client client1 = clientDao.getClientById(clientID);
if (client1 instanceof Societe) {
((Societe) client1).getCommentaire();
}
Depending on your use case, it may be useful to map the result of the client query to a ClientDescriptor object which contains all the fields for all client types and returns either nulls or blanks. This means you don't have to keep checking for client type everywhere;
public class ClientDTO {
//client fields
private String nomResponsable = "";
....
//subclass 1 fields.... initialize to empty
//subclass 2 fields .... initialize to empty
public ClientDTO (Client client) {
// set fields for client entity
}
public ClientDTO (Societe societe) {
this (societe);
// set societe fields.
}
// other constructors.
}
You can modify your getClientByID method to accept an additional argument which will say what type of entity your want to retrieve and get back:
public class ClientDaoImpl implements ClientDao {
#PersistenceContext
private EntityManager em;
public <T extends Client> T getByID(int id_client, Class<T> klass) {
return em.find(klass, id_client);
}
}
And you can use this dao in the following manner:
Societe societe = clientDao.getByID(42, Societe.class);
Particulier particulier = clientDao.getByID(43, Particulier.class);

Node will not persist to Neo4j

I have a Role node that contains some privileges that I am trying to persist into Neo4j. When I construct the object, I see that the privileges exist, but after the save call they disappear.
Here's my Role Node:
#NodeEntity
public class Role {
#GraphId Long id;
private RoleType roleType;
//#RelatedToVia(type="HAS_ROLE", direction=Direction.OUTGOING)
private List<Person> users;
private List<Privilege> defaultPrivileges;
//private List<Task> tasks;
public Role(){}
public Role(RoleType roleType){
this.roleType=roleType;
this.defaultPrivileges=roleType.getDefaultPrivileges();
}
}
Here's my save:
admin= roleRepository.save(admin);
Before I save the object it is fully populate and after it's empty. Any ideas as to why that might be
EDIT:
The code causing the issue is in my Privilege class.
This does not work:
public class Privilege {
private String name;
public Privilege(PrivilegeType pt) {
this.name = pt.name();
}
}
This works:
public class Privilege {
private String name;
public Privilege(String pt) {
this.name = pt;
}
}
Why would that be causing it to not persist? What am I missing in my RoleRepository?
It reloads the entity after storing it, and by default it only loads a shallow copy of related information.
you can use template.fetch(role.users) or template.fetch(role.tasks)
or add #Fetch to the tasks list for instance.

What is the appropriate way persist extended classes?

Consider the diagram:
I've been working with JPA for a short time and, so far, I have never had the need to persist extended classes... As you can see by the example, SNMPNode, IPNode, etc are all extended classes from Node that is also extended from GeoLocation.
I understand that I can annotate the master classes with #MappedSuperclass and IPNode and SNMPNode will inherit their properties for persisting... But in this scenario I will end up with nearly identical tables and, to my understanding, instead of doing that I could just group all information in Node and work with a single table.
Is this the way persistence of extended classes on JPA work or my concepts are wrong?
Same thing as a resumed piece of code:
public class Node extends GeoLocation {
private String name;
private Group group;
private Location location;
private Type type;
private Company company;
}
public class IPNode extends Node {
private Long id;
private String ipAddress;
}
public class SNMPNode extends Node {
private Long id;
private SNMPServer server;
}
[[ EDITED AFTER ANSWER FROM THIS POINT ]]
For the sake of contributing, here's a sample of what I end up doing:
INode:
public interface INode {
public Long getId();
public void setId(Long id);
public String getName();
public void setName(String name);
public String getIpAddress();
public void setIpAddress(String ipAddress);
public String getCommunity();
public void setCommunity(String community);
}
Node:
#Entity
#DiscriminatorValue("N")
#DiscriminatorColumn(name="NODE_TYPE",discriminatorType=DiscriminatorType.STRING, length=20)
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Node extends GeoLocation implements INode {
#Id
#GeneratedValue
private Long id;
private String name;
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
(... Overrides from INode ...)
}
IPNode:
#Entity
#DiscriminatorValue("I")
public class IPNode extends Node {
private String ipAddress;
public String getIpAddress() { return this.ipAddress;}
public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; }
(... Overrides from INode ...)
}
SNMPNode:
#Entity
#DiscriminatorValue("S")
public class SNMPNode extends Node {
private String community;
public String getCommunity() { return community;}
public void setCommunity(String community) { this.community = community; }
(... Overrides from INode ...)
}
NodeRepository:
#Repository
public interface NodeRepository extends JpaRepository<Node, Long> { }
So now I can do stuff like this:
#ContextConfiguration("classpath:/spring/application-context.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class NodeRepositoryTest {
#Autowired
NodeRepository repo;
private INode node;
#Before
#Transactional
#Rollback(false)
public void setup() {
node = new IPNode();
node.setName("ipNode");
node.setIpAddress("1.1.1.1");
repo.save((IPNode)node);
node = new SNMPNode();
node.setName("snmpNode");
node.setIpAddress("2.2.2.2");
node.setCommunity("some text");
repo.save((SNMPNode)node);
}
#Test
#Transactional
public void Test() throws Exception {
INode testNode = repo.findOne(1L);
assertNotNull(testNode);
}
}
Both Node types are saved on the same table and so their keys can't repeat... My REST URL can grab them by /nodes/1 or /nodes/2, which was my main goal after all...
Thanks :)
If your base class is annotated with #MappedSuperclass then inheritance is only relevant in the OOP context. The #MappedSuperclass properties are simply copied to each sub-class associated database table and you can only query for sub-class entities.
Single table inheritance yields the best performance (no join or union is involved) at the price of not being able to declare not-nullable all specific sub-class properties (since all base and all sub-class specific properties go to a single database table).
With joined inheritance tables you can have the base class properties in a base database table, and each specific sub-class has it's own associated table. The sub-class table is linked with the base database table through a FK, so you need to join these tables to fetch a sub-class entity. As opossed to #MappedSuperclass, the base class is queryable since both the OOP context and the database reflect the inheritance model.

Categories

Resources