I've got a query which returns data from several tables. In the application, these tables are classes one within another, for example a Client has several Orders, each Order has several OrderDetails, each OrderDetail has several Products, and so on... But I can't figure out a proper way to build the entire object in the app since the query returns one row for (let's just say) each product, so I have one client repeated over and over for every product it has bought.
So far I've tried this terribly inefficient code, and it works, problem is, it takes too much time for the app to process all of this information when it retrieves several clients.
boolean orderFound = false;
for (Order order1 : orders) {
if (order1 .getId() == order.getId()) {
orderFound = true;
if (od.getId() != 0) {
boolean odFound = false;
for (OrderDetail orderdetail : order1.getOrderDetail()) {
if (orderDetail.getId() == od.getId()) {
if (prod.getId() != 0) {
odFound = true;
boolean prodFound= false;
for (Product product: orderDetail.getProducts()) {
if (product.getId() == product.getId()) {
prodFound= true;
}
}
if (!prodFound) {
orderDetail.getProducts().add(dia);
}
}
if (!odFound) {
order1.getOrderDetail().add(od);
}
}
}
}
if (!orderFound) {
if (order.getId() != 0) {
orders.add(order);
This works, but there's gotta be a better way and I haven't found it. I've been told this can be solved using HashSets but I still don't know how to use them. Any help will be appreciated.
If you are open to using third party libraries, I think this is what you are looking for:
How to use hibernate to query for an object with a nested object that has a nested collection of objects
Related
I have a String array named andOrButtonFilter which stores and or filters selected by user.
Also two ArrayList named column and value storing column names and their values respectively.
I want the current query to append to the previous query and show the results
But my query is not being appended to the previous query, it is showing individual results.
For eg:
if name=xyz is first query and
age=26 is second query
It does not results with name=xyz and age=26 . It is only showing results for age=26 when executed for the second time.
Where am I going wrong?
This is the code I am using at the moment:
for (int i=0; i<andOrButtonFilter.length; i++)
{
if(andOrButtonFilter[i]=="and")
{
Conjunction conjunction =Restrictions.conjunction();
if ((column.get(i) != null) && (value.get(i)!=null))
{
conjunction.add(Restrictions.or(Restrictions.eq(column.get(i), value.get(i))));
criteriaQuery.add(conjunction);
}
}
else if(andOrButtonFilter[i]=="or")
{
Disjunction disjunction =Restrictions.disjunction();
if ((column.get(i) != null) && (value.get(i)!=null))
{
disjunction.add(Restrictions.or(Restrictions.eq(column.get(i), value.get(i))));
criteriaQuery.add(disjunction);
}
}
else
{
criteriaQuery.add(Restrictions.eq(column.get(i), value.get(i)));
}
}
I can find a few problems with you code.
1) You compare strings with == instead of equals. So your code always goes into the last section criteriaQuery.add(Restrictions.eq(column.get(i), value.get(i)));
2) In your conjunction/disjunction code you still use Restrictions.or which is kind of wrong. You don't even need Restrictions.or or Restrictions.and because Conjunction is adding the restrictions with AND anyway and Disjunction is adding with OR anyway.
3) On each iteration you add separate disjunction which is basically a single criterion and won't work as you expect.
I would try with something like:
Disjunction disjunction =Restrictions.disjunction();
Conjunction conjunction =Restrictions.conjunction();
for (int i=0; i<andOrButtonFilter.length; i++)
{
if("and".equals(andOrButtonFilter[i]))
{
if ((column.get(i) != null) && (value.get(i)!=null))
{
conjunction.add(Restrictions.eq(column.get(i), value.get(i)));
}
}
else if("or".equals(andOrButtonFilter[i]))
{
if ((column.get(i) != null) && (value.get(i)!=null))
{
disjunction.add(Restrictions.eq(column.get(i), value.get(i)));
}
}
else
{
criteriaQuery.add(Restrictions.eq(column.get(i), value.get(i)));
}
}
criteriaQuery.add(conjunction);
criteriaQuery.add(disjunction);
I am not saying that exact code will work because I haven't tested it ;) but you get the idea and you can debug from there.
I'm trying to save with GreenDAO an entity called hotel. Each hotel has a relation one-to-many with some agreements and each agreement has got... well, a picture is worth a thousand words.
Now, what I do is the following:
daoSession.runInTx(new Runnable() {
#Override
public void run() {
ArrayList<Hotel> listOfHotels = getData().getAvailability();
for(Hotel h : listOfHotels)
{
List<HotelAgreement> hotelAgreements = h.getAgreements();
for(HotelAgreement ha : hotelAgreements) {
ha.setHotel_id(h.getHotel_id());
HotelAgreementDeadline hotelAgreementDeadline = ha.getDeadline();
List<HotelRemark> hr = hotelAgreementDeadline.getRemarks();
List<HotelAgreementDeadlinePolicies> hadp = hotelAgreementDeadline.getPolicies();
daoSession.getHotelReportDao().insertOrReplaceInTx( h.getReports() );
daoSession.getHotelPictureDao().insertOrReplaceInTx( h.getPictures() );
daoSession.getHotelRemarkDao().insertOrReplaceInTx(hr);
daoSession.getHotelAgreementDeadlinePoliciesDao().insertOrReplaceInTx(hadp);
daoSession.getHotelAgreementDeadlineDao().insertOrReplace(hotelAgreementDeadline);
daoSession.getHotelAgreementDao().insertOrReplace(ha);
}
// daoSession.getHotelReportsDao().insertOrReplace( getData().getReports() );
}
daoSession.getHotelDao().insertOrReplaceInTx(listOfHotels);
}
});
This, of course, does not work. I get a "Entity is detached from DAO context" error on the following line:
HotelAgreementDeadline hotelAgreementDeadline = ha.getDeadline();
I understand this is because I try to get the Agreements from a Hotel entity which does not come from the database, but from another source (a web service, in this case). But why does this happen with ha.getDeadline() and not with h.getAgreements()?
Now, I have the Hotel object and it does include pretty much all data: agreements, deadline, policies, remarks, pictures, report. I'd just like to tell GreenDAO: save it! And if I can't and I have to cycle through the tree - which is what I'm trying to do with the code above - how am I supposed to do it?
Here I read that I have to "store/load the object first using a Dao". Pretty awesome, but... how does it work? I read the greenDAO documentation about relations but couldn't find anything.
Thank you to everybody who's willing to help :-)
At some point, when you get the response from the webservice, you are creating new entity objects and filling them with the info. Try inserting each new object in the DB just after that.
If you want, you can insert, for example, all n Agreement for an Hotel using insertOrReplaceInTx, but you shouldn't use any relation before all the involved objects are in the DB.
I think that greendao team have to add the following control in the method
getToOneField() like in the getToManyList()
if(property == null){
code already generated by greendao plugin
}
return property;
so in your case in HotelAgreements class
#Keep
public DeadLine getDeadLine {
if(deadLine == null) {
long __key = this.deadLineId;
if (deadLine__resolvedKey == null || !deadLine__resolvedKey.equals(__key)) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
DeadLineDao targetDao = daoSession.getDeadLineDao();
DeadLine deadLineNew = targetDao.load(__key);
synchronized (this) {
deadLine = deadLineNew;
deadLine__resolvedKey = __key;
}
}
}
return deadLine;
}
adding the control
if(deadLine == null) {
...
}
so if you receive data from rest json
the object is populated and getProperty() method return property field from object not from database just like it does with Lists
then you can insert or replace it
Then, when you load or load deeply object from db the property is null and greendao take it from DB
I have this code that dumps documents into MongoDB once an ArrayBlockingQueue fills it's quota. When I run the code, it seems to only run once and then gives me a stack trace. My guess is that the BulkWriteOperation someone has to 'reset' or start over again.
Also, I create the BulkWriteOperations in the constructor...
bulkEvent = eventsCollection.initializeOrderedBulkOperation();
bulkSession = sessionsCollection.initializeOrderedBulkOperation();
Here's the stacktrace.
10 records inserted
java.lang.IllegalStateException: already executed
at org.bson.util.Assertions.isTrue(Assertions.java:36)
at com.mongodb.BulkWriteOperation.insert(BulkWriteOperation.java:62)
at willkara.monkai.impl.managers.DataManagers.MongoDBManager.dumpQueue(MongoDBManager.java:104)
at willkara.monkai.impl.managers.DataManagers.MongoDBManager.addToQueue(MongoDBManager.java:85)
Here's the code for the Queues:
public void addToQueue(Object item) {
if (item instanceof SakaiEvent) {
if (eventQueue.offer((SakaiEvent) item)) {
} else {
dumpQueue(eventQueue);
}
}
if (item instanceof SakaiSession) {
if (sessionQueue.offer((SakaiSession) item)) {
} else {
dumpQueue(sessionQueue);
}
}
}
And here is the code that reads from the queues and adds them to an BulkWriteOperation (initializeOrderedBulkOperation) to execute it and then dump it to the database. Only 10 documents get written and then it fails.
private void dumpQueue(BlockingQueue q) {
Object item = q.peek();
Iterator itty = q.iterator();
BulkWriteResult result = null;
if (item instanceof SakaiEvent) {
while (itty.hasNext()) {
bulkEvent.insert(((SakaiEvent) itty.next()).convertToDBObject());
//It's failing at that line^^
}
result = bulkEvent.execute();
}
if (item instanceof SakaiSession) {
while (itty.hasNext()) {
bulkSession.insert(((SakaiSession) itty.next()).convertToDBObject());
}
result = bulkSession.execute();
}
System.out.println(result.getInsertedCount() + " records inserted");
}
The general documentation applies to all driver implementations in this case:
"After execution, you cannot re-execute the Bulk() object without reinitializing."
So the .execute() method effectively "drains" the current list of operations that have been sent to it and now contains state information about how the commands were actually sent. So you cannot add more entries or call .execute() again on the same instance without reinitializing .
So after you call execute on each "Bulk" object, you need to call the intialize again:
bulkEvent = eventsCollection.initializeOrderedBulkOperation();
bulkSession = sessionsCollection.initializeOrderedBulkOperation();
Each of those lines placed again repectively after each .execute() call in your function. Then further calls to those instances can add operations and call execute again continuing the cycle.
Note that "Bulk" operations objects will store as many items as you want to put into them but will break up requests to the server into maximum amounts of 1000 items. After execution the state of the operations list will reflect exactly how this is done should you want to inspect that.
I face a problem in using AbstractTableModel, i use linked list as a container for data , and i fetch records from table from db then i put it in linked list in table model then i male jable.setModel(model). THE PROBLEM i face that the last record i fetch from table from db is repeated n times since n is the number of records in database.
and when i make model.getIndextOF(anAppointmentDate); each time return 0 , so i think it each time the object in inserted in the same place ? i may be wrong , but that what i think
public class appointmentModel extends AbstractTableModel {
List<appointmentDate> patientAppointment;
public appointmentModel() {
patientAppointment = new LinkedList<appointmentDate>(); // linked list
}
public int getRowCount() {
return patientAppointment.size();
}
public int getColumnCount() {
return 2;
}
public String getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return patientAppointment.get(rowIndex).getDateOFAppointment();
} else if (columnIndex == 1) {
return patientAppointment.get(rowIndex).getTimeOfAppointment();
} else {
return "Not found";
}
}
public String getColumnName(int column) {
if (column == 0) {
return "date";
} else if (column == 1) {
return "time";
} else {
return "not found";
}
}
public void insertRecord(appointmentDate anAppointmentDate)
{
list.add(anAppointmentDate);
fireTableRowsInserted(list.size()-1, list.size()-1);
System.out.println(list.indexOf(anAppointmentDate)); // each time it prints 0
}
//////////
here where i use the model
while (resultSet.next()) {
N_Date= resultSet.getDate("appointDate");
anAppointment.setDateOFAppointment(N_Date);
N_time = resultSet.getString("appointTime");
anAppointment.setTimeOfAppointment(N_time);
tableModel.insertRecord(anAppointment);
}
jTable.setModel(tableModel);
The output i have is the last record repeated in all table records ,plz help!
You are using the same reference to an AppointmentDate object, and change only its internal state.
Thus everytime you add the same object to the list. So with the last loop iteration you set all objects inside the list to have the data of the last row.
To fix this, instantiate a new AppointmentDate() on each loop iteration:
while (resultSet.next()) {
AppointmentDate anAppointment = new AppontmentDate();
// the rest is the same
}
Note also that the class name should start with an upper-case letter - i.e. AppointmentDate, not appointmentDate.
Found the problem!
You don't show quite enough code around "where you use the model" but it looks like you are re-using the same object for each insert. You've got this object, you set its attributes from what comes out of the DB, and then you stash it in the list.
Well guess what: It's the same object every time, so it's bound to have the same value every time! If you want different values in your list, you'll need to use distinct objects. Don't worry, this is a common enough beginner's mistake.
A sensible way to do this would be to construct a new appointmentDate for every DB record. You may want to initialize the data right in the constructor.
Finally, note that if appointmentDate is a class name, it should (by convention) begin with an uppercase letter!
Finally (some more): LinkedList is efficient at inserts, but performs horribly at retrieval, i.e. the get(n) thing. I'd expect there to be a lot more scrolling and displaying from your list than inserting, so I'd use the List implementation that's much better performing here: ArrayList. It works the same, is only marginally slower at inserts and much faster at retrieval. But that's just additional information for you. Performance isn't so important for a small project like this.
Is it possible to query a collection that is dumped in a heap dump? I can obviously browse that collection using something like Eclipse MAT, but would really love to be able to actually call a getter on the collection object. This would obviously be a lot clearer than going through segments in a ConcurrentHashMap trying to find the mapping I need.
I suppose what I'm looking for is some way to 'rehydrate' the dumped state of a named collection so that it can then be manipulated using the standard APIs.
Does anyone know of any such utilities, or, if not, can someone provide some sample code or pointers as to how to achieve this?
You should be able to query all collections or single one with Object Query Language (OQL) in jhat.
You can't necessarily invoke arbitrary methods but you can write some complicated queries using the available functions.
A. Sundararajan has some interesting blog posts on the subject that showcase what you can do. See here and here.
For instance, you can find all instances of java.util.HashMap that have a key test with the following query:
select s from java.util.HashMap s where contains(s.table, function(it) {
if (it && it.key && it.key.value && it.key.value.toString() == 'test') {
return true;
}
return false;
})
This should find the same key in a java.util.concurrent.ConcurrentHashMap:
select s from java.util.concurrent.ConcurrentHashMap s where contains(s.segments, function(it) {
if (!it || !it.table) {
return false;
}
var i, e;
for (i=0; i < it.table.length; i = i + 1) {
e = it.table[i];
if (e) {
return e.key && e.key.value && e.key.value.toString() == 'test';
}
}
return false;
})