OrientDB: delete record and references created with Object API - java

I am using the OrientDB 2.1.6 Object API.
I have two POJOs with a 1 to N relationship like this:
public static class Results {
private String userId;
private String templateId;
private Double totalLength;
private List<String> visibleFields;
private Boolean filterable;
#OneToMany(orphanRemoval = true)
private List<ResultItem> items;
//Generic getters and setters
}
public static class ResultItem {
private String id;
private String vsId;
private String entryTemplateId;
private String objectType;
private String objectTypeLabel;
private String capabilityComment;
private Boolean currentVersion;
private Double contentSize;
private String name;
private String objectStoreId;
private String mimeType;
private HashMap<String, String> attributes;
private Date dateLastModified;
//generic getters and setters
}
This creates two classes in OrientDB. If I delete a Results instance using the Object API, it will delete associated ResultItem rows correctly.
I am trying to delete a particular ResultItem record using the "console" like this:
orientdb {db=test}> find references #15:6392 Found
[{rid:#15:6392,referredBy:[1]}] in 0.014000 sec(s).
orientdb {db=test}> delete from ResultItem where #rid=#15:6392 Delete
record(s) '1' in 0.006000 sec(s).
orientdb {db=test}> find references #15:6392 Found
[{rid:#15:6392,referredBy:[1]}] in 0.014000 sec(s).
The console output suggests that the record has been deleted but it continues to contain a "reference".
This manifests itself as a problem when I go back to the Object api and try to db.detachAll(results, true);. It throws this exception which I assume is due to the the orphan relationship.
Caused by: java.lang.NullPointerException
at com.orientechnologies.orient.object.db.OObjectLazyList.convertAndDetachAll(OObjectLazyList.java:456)
at com.orientechnologies.orient.object.db.OObjectLazyList.convertAndDetachAll(OObjectLazyList.java:432)
at com.orientechnologies.orient.object.db.OObjectLazyList.detachAll(OObjectLazyList.java:424)
at com.orientechnologies.orient.object.enhancement.OObjectProxyMethodHandler.detachAll(OObjectProxyMethodHandler.java:165)
at com.orientechnologies.orient.object.enhancement.OObjectEntitySerializer.detachAll(OObjectEntitySerializer.java:261)
at com.orientechnologies.orient.object.db.OObjectDatabaseTx.detachAll(OObjectDatabaseTx.java:809)
at com.orientechnologies.orient.object.db.OObjectDatabaseTx.detachAll(OObjectDatabaseTx.java:327)
How can I delete the relationship along with the record?

I tried your case and I got your same results.
This is a limitation about the references because there's no check on #RID consistency and when you delete a document, the deletion of all references would activate a full scan of the DB to search all the documents linked to the first and then drop the references.
This would be a very expensive operation and it would take a lot of time, this is one the reasons because using edges is reccomended instead of the LINKS, LINKLIST,...
Hope it helps

Related

Question about Springboot, mongoDB relations and API

So I'm trying to create a project based in some weather forecast API and the data comes in different objects like:
public class WeatherForecast{
private String local;
private int maxTemp;
private int minTemp;
private int precipitationId;
}
public class Precipitation{
#Id
private int id;
private String descriptionEn;
private String descriptionCh;
...
}
So, I want to store this information and obtain the description of the Precipitation in the language that I desire, without receiving an WeatherForecast with the description of 10+ languages.
I searched a lot about defining relations between the tables but I couldn't find something related to relationships by id's. I found that I could use,
#DbRef
private Precipitation precipitation;
but I couldn't understand how it can interpret the Id without passing in the constructor.
And, finally, I want to understand if it's a good practice to send the two objects
separately to the database and try to workout some functionality to get the object I want, something like this:
public class WeatherForecast{
private String local;
private int maxTemp;
private int minTemp;
private String description;
}
using criteria, queries, or other things without extracting the two tables and searching in Precipitations for the desired description language.

Hibernate Criteria restricting on an object that is in list inside a different class

I have 2 classes with the following association:
public class Entry {
private Long id;
private String poNumber;
private List<Comment> comments;
}
public class Comment{
private Long id;
private Reason reason;
}
I'm using Hibernate criteria to set up restrictions on a list of Entry objects:
Criteria criteria = ((HibernateEntityManager) entityManager).getSession().createCriteria(Entry.class, "entry");
I have a search form that gives me lists of objects. For restricting on "poNumber", given List<String> poNumbers I do this:
criteria.add(Restrictions.in("poNumber", poNumbers));
But I don't know what to do when, given List<Reason> reasons, how to restrict on reason. I am restricting on the same Criteria object (ie. of class Entry).
(Related to Fetching objects of class B stored in a list inside class A with Hibernate Criteria)
This will still return objects of class Entry:
criteria.createAlias("comments", "comment")
.add(Restrictions.in("comment.reason", reasons));

JDBC Domain Design and Relationships

I've used Hibernate / JPA in the past, now using a combination of Spring JDBC and MyBatis.
With JPA/ Hibernate if you had a Customer, which had an address you would have a domain structure similar to code below. (minus all the annotations / config / mappings).
Does this still make sense when using JDBC or MyBatis. This is composition domain design from what I know, has-a, belongs-to, etc. However most examples I've seen of JDBC code they have domain object that bring back the IDs rather than collection, or flatten the data. Are there any performance benefits from either approach, maintainability, etc. Having worked with JPA first I'm not sure what the JDBC way of doing things are.
public class Customer {
private Long id;
private String userName;
private String password;
private String firstName;
private String lastName;
private Collection<Address> addresses
...
}
public class Address {
private Long id;
private String streetAddress1;
private String streetAddress2;
private String city;
private State state;
private String postalCode;
}
public class State {
private Long id;
private String code;
private String name;
private Country country;
}
public class Country {
private Long id;
private String code;
private String name;
}
I come across an example and here was one of their classes.
public class Question {
private long questionId;
private long categoryId;
private long userId;
private long areaId;
private String question;
private String verifyKey;
private Date created;
private User user;
private List<Answer> answers;
private long answerCount;
private String name;
// getters and setters omited...
}
Why would you fetch the userId, areaId, and categoryId instead of actually fetching the associated object? The ID is likely of no use to the front end user, I suppose you could use the ID to issue another query to fetch additional data, but seems inefficient making another round trip to the database.
You can look at this domain object as a "footprint" of database table. In your example, userId, areaId and categoryId from Question are most likely foreign keys from corresponding tables. You could never need full object data in the moment of Question creation and retrieve it later with separate db request. If you fetch all associated objects at once, you will hit at least one additional table per object (by join-s or subselect-s). Moreover, that's actually the same that Hibernate does. By default, it loads domain object lazily and hits database again if uninitialized associated object is needed.
At that time, it is better to fetch those objects that a domain object can't exist without. In your example, Question and List are coupled.
Of course, if you need user, or category, or any other associated object again in some another place of application (assume the reference to previously retrieved object has been lost), you will hit the database with same query. It should be done and could seem inefficient, because both plain JDBC and SpringJDBC have no intermediate caching unlike Hibernate. But that's not the purpose JDBC was designed for.

Sending GSON string from client to server Design issue in java

I am building an application which allows restaurant guests to order food and send to server.
What i have considered is to
1) create a class Order.java class
public class Order
{
private Intger tableId;
private Integer restaurantId;
private Integer foodId;
private Integer foodQuantity;
getter and setters
}
2) This class object will be populated with guests order and an ArrayList of objects of the class will be sent to server as Gson String.
Now if an order consist of some 7 items, Then the arraylist will have 7 objects, but tableId and restaurantId will be same 7 times.
can you suggest a better design where in I can associate restaurantId and tableId with the entire arraylist.
Thanks.
There is no right solution, it would depend on your needs, one possible solution would be something like:
public class Order {
private int tableId;
private int restaurant;
private List<OrderItem> items;
// setters and getters
}
public class OrderItem {
private int itemId; // foodId
private int quatity; // foodQuantity
// setters and getters
}
But if you were in a situation that the information comes not normalized, like you suggested (in which tableId is repeated for every single food ordered), I would consider to implement a normalization process that will return a structure with the classes I draft above. But if you are implementing it, please consider to make it as normalized as possible.

Hibernate - How to persist an entity but disregarding certain fields?

I have an Entity with several fields:
#Entity
public class Leilighet {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private Long leilighetId;
private String navn;
private String beskrivelse;
private String adresse;
private String postNr;
private String postSted;
private double pris;
//The following fields should not be stored:
private String filename;
private String filetype;
private String filesize;
private byte[] filebin;
....
}
I have a corresponding form and Action that will populate this object and persist it to mySql.
This is all good when it comes to storing new "Leilighet"-entities.
But when im using this form to "edit" an existing "Leilighet", I have stumbled upon something i cant figure out what to do.
For editing purposes i do not want to load the entire uploaded file. It is enough to just show the filename to indicate that there is a file present. If the user chooses a new File then it should be overwritten, but if the user chooses nothing then the present file should be kept.
But I cant figure out how to make hibernate do what i want. Unless i populate the filebin with the actual file, hibernate will just delete the file.
How can I tell hibernate to just update the other fields and not the filefields?
Hibernate supports loading individual properties lazily. See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#performance-fetching-lazyproperties for details.
Or you could just use a DTO with only the fields you want in this specific use-case, and execute a query with the appropriate projections in order to populate this DTO from the database.

Categories