Apache Cayenne ResultIterator and prefetch joint - join

We are using Cayenne with something like
ResultIterator<SomeMain> lvSomeMainList = ObjectSelect
.query(Anlstamm.class)
.and(SomeMain.ORGUNIT_NR.eq(pvOrgUnitNr))
.prefetch(SomeMain.RELATION1.joint())
.prefetch(SomeMain.RELATION2.joint())
.prefetch(SomeMain.RELATION3.joint())
.iterator(gvContext);
for (SomeMain bvSomeMain: lvSomeMainList) {
bvSomeMain.getMethod_relation1();
...
}
Cayenne executes the correct joins on DB-Level but instead of fully resolve bvSomeMain, getMethod_relation1 triggers a new select with the already prefetched RELATION1.
We are using Apache Cayenne 4.0
Thanks for a hint.

Related

Grails 3 Entity not saved when properties set in EntityClass

I occure a problem which I do not understand. Following code does not work:
AccountingEntity accountingEntity = AccountingEntity.get(params.id);
accountingEntity.setLifecycleStatusToArchived();
accountingEntity.save(flush:true);
Where the method setLivecylceStatusToArchived looks like:
void setLifecycleStatusToArchived() {
this.lifecycleStatus = AccountingEntity.LIFECYCLE_ARCHIVED; //predefined static variable
this.considerForRankingJob = false;
this.dateArchived = new Date();
}
Problem is, that the entity is not updated.
No validation erros when I use accountingEntity.validate() in advance.
However, this code works:
AccountingEntity accountingEntity = AccountingEntity.get(params.id);
accountingEntity.setDateArchived(new Date());
accountingEntity.setConsiderForRankingJob(false);
accountingEntity.setLifecycleStatus(AccountingEntity.LIFECYCLE_ARCHIVED);
accountingEntity.save(flush:true);
The code did not work any more after update from Grails 3.2.9 to 3.3.0.RC1 (Gorm 6.1.5) unless I followed all the steps in the guide (http://docs.grails.org/3.3.x/guide/upgrading.html) and the rest of the code is working properly (also database accesses etc.)
Has anybody an idea? What the problem could be?
Thanks in advance and best regards!
The short answer is dirty checking. When you are setting properties inside the instance method Grails doesn't know they are dirty.
See the following github issue for how to resolve the problem:
https://github.com/grails/grails-data-mapping/issues/961
you have 2 options:
call markDirty every time you change an internal field. This will be
better for performance or as per
http://gorm.grails.org/latest/hibernate/manual/index.html#upgradeNotes
use
hibernateDirtyChecking: true

How to setup service method caching in grails

My application has a couple of services that make external calls via httpClient (GET and POST) that are unlikely to change in months, but they are slow; making my application even slower.
Clarification: this is NOT about caching GORM/hibernate/queries to my db.
How can I cache these methods (persistence on disk gets bonus points...) in grails 2.1.0?
I have installed grails-cache-plugin but it doesn't seem to be working, or i configured it wrong (very hard to do since there are 2-5 lines to add only, but i've managed to do it in the past)
I also tried setting up an nginx proxy cache in front of my app, but when i submit one of my forms with slight changes, I get the first submission as result.
Any suggestions/ideas will be greatly appreciated.
EDIT: Current solution (based on Marcin's answer)
My config.groovy: (the caching part only)
//caching
grails.cache.enabled = true
grails.cache.clearAtStartup = false
grails.cache.config = {
defaults {
timeToIdleSeconds 3600
timeToLiveSeconds 2629740
maxElementsInMemory 1
eternal false
overflowToDisk true
memoryStoreEvictionPolicy 'LRU'
}
diskStore {
path 'cache'
}
cache {
name 'scoring'
}
cache {
name 'query'
}
}
The important parts are:
do not clear at startup (grails.cache.clearAtStartup = false)
overflowToDisk=true persists all results over maxElementsInMemory
maxElementsInMemory=1 reduced number of elements in memory
'diskStore' should be writable by the user running the app.
Grails Cache Plugin works quite well for me under Grails 2.3.11. Documentation is pretty neat, but just to show you a draft...
I use the following settings in Config.groovy:
grails.cache.enabled = true
grails.cache.clearAtStartup = true
grails.cache.config = {
defaults {
maxElementsInMemory 10000
overflowToDisk false
maxElementsOnDisk 0
eternal true
timeToLiveSeconds 0
}
cache {
name 'somecache'
}
}
Then, in the service I use something like:
#Cacheable(value = 'somecache', key = '#p0.id.toString().concat(#p1)')
def serviceMethod(Domain d, String s) {
// ...
}
Notice the somecache part is reused. Also, it was important to use String as key in my case. That's why I used toString() on id.
The plugin can be also set up to use disk storage, but I don't use it.
If it doesn't help, please provide more details on your issue.
This may not help, but if you upgrade the application to Grails 2.4.x you can use the #Memoize annotation. This will automagically cache the results of each method call based upon the arguments passed into it.
In order to store this "almost static" information you could use Memcached or Redis as a cache system. (There are many others)
This two cache systems allows you to store key-value data (in your case something like this "key_GET": JSON,XML,MAP,String ).
Here is a related post: Memcached vs. Redis?
Regards.

web server memory leak issue

i'm create a dating website using symfony 1.4 (it's my first project using symfony). the problem is there server freezes if there is only 10 or less users online. i tryied optimizing my js, css, sprites using yslow i got grade A but still the problem is always there. that's why i think the way i build the application might be wrong so here is the website naijaconnexion.com i'm asking u for advices and things to do so i overcome this problem
If i wasn't clear enough just ask, if you want cpanel admin access i'll post it
i realy realy needs your help
for instance i have this code on my home page action does it seems ok or it needs to be optimized and how
$this->me = $this->getUser()->getGuardUser()->getPerson();
$this->cities = Doctrine_Core::getTable('City')->findByDql("zipcode=''");
$this->countries = Doctrine_Core::getTable('City')->findByDql("zipcode='10'");
$this->contacts = $this->me->getContacts();
$this->favorites = $this->me->getFavorites();
$this->matches = $this->me->getMatches();
$this->pager = new sfDoctrinePager('Conversation', sfConfig::get('app_home_conversations_per_page'));
$this->pager->setQuery($this->me->getConversationsQuery());
$this->pager->setPage($request->getParameter('page', 1));
$this->pager->init();
without HYDRATE_ARRAY
i can do this
if i use HYDRATE_ARRAY
will i be able to do stuff like $this->contacts[0]['username'];
help please
The problem is doctrine...
Try to fetch the needed values as array and set a limit!
How many objects are returned by the following queries:
$this->cities = Doctrine_Core::getTable('City')->findByDql("zipcode=''");
$this->countries = Doctrine_Core::getTable('City')->findByDql("zipcode='10'");
$this->contacts = $this->me->getContacts();
$this->favorites = $this->me->getFavorites();
$this->matches = $this->me->getMatches();
? Do not forget that they are object with references to other objects!
And yes, this will work $this->contacts[0]['username'];.
if you join the tables with the doctrine query, you can access related entities too - without executing additional queries.
$this->contacts = Doctrine_Core::getTable('Contact')
->createQuery('c')
->leftJoin('c.Users u')
->addWhere('...')
->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
$this->contacts[0]['Users'][0]['username']

How to get the comments of a JIRA issue in a custom release note template

We upgraded our jira to version 5.0.5 today, before we were running version 4.2.4. In that version we had made a custom release notes template that would also show all comments made on an issue. To do that we had to be able to get a CommentManager object. We did this like this:
#foreach ($issue in $issueType.issues)
#if($issueType.issues.size() > 0)
#set ($comments = $action.ComponentManager.CommentManager.getComments($issue))
#if ($comments)
#foreach ($comment in $comments)
...
That worked fine in JIRA 4.2.4 however it isn't working anymore in jira 5.0.5, does anyone know how i can get a CommentManager object again when creating a custom release notes template in JIRA 5.0.5 or how to get a CommentManager object some other way, without using $action for example?
In your vm template, write this:
#set ($componentAccessorClass = $constantsManager.getClass().getClassLoader().findClass('com.atlassian.jira.component.ComponentAccessor'))
#set ($componentAccessorConstructor = $componentAccessorClass.getConstructor())
#set ($componentAccessor = $componentAccessorConstructor.newInstance())
Now you have access to the Component Accessor which can get you pretty much anything you want, including the Comment Manager.
Now, all you have to do is call getCommentManager() on your Component Accessor variable.
#set($commentManager = $componentAccessor.getCommentManager() )
Hope that helps ! :)
JiraWebActionSupport has the following deprecated method that provided the component manager object.
#Deprecated
public ComponentManager getComponentManager()
{
return ComponentManager.getInstance();
}
and https://developer.atlassian.com/display/JIRADEV/Creating+a+Custom+Release+Notes+Template+Containing+Release+Comments
has some Velocity code but looking at the 5.0.1 source it looks like Velocity is no longer being used?
I would file an Improvement at https://jira.atlassian.com/browse/JRA to add a getCommentManager method to JiraWebActionSupport.java
this is the way i used in jira to get a componentmanager object, once you have the componentmanager object it's rather easy to do the rest:
#set ($componentManagerClass = $constantsManager.getClass().getClassLoader().findClass('com.atlassian.jira.ComponentManager'))
#set ($method = $componentManagerClass.getDeclaredMethod('getInstance', null))
#set ($componentManager = $method.invoke(null, null))
i'm using this solution now, and it can be rather helpfull to others to almost get any kind of class using the constantsmanager.

db4o issue with graph of objects

I am a new to db4o. I have a big problem with persistance of a graph of objects. I am trying to migrate from old persistance component to new, using db4o.
Before I peristed all objects its graph looked like below (Take a look at Zrodlo.Metadane.abstrakt string field with focused value) [its view from eclipse debuger] with a code:
ObjectContainer db=Db4o.openFile(DB_FILE);
try {
db.store(encja);
db.commit();
} finally{
db.close();
}
After that, I tried to read it with a code:
ObjectContainer db=Db4o.openFile((DB_FILE));
try{
Query q = db.query();
q.constrain(EncjaDanych.class);
ObjectSet<Object> objectSet = q.execute();
logger.debug("objectSet.size" + objectSet.size());
EncjaDanych encja = (EncjaDanych) objectSet.get(0);
logger.debug("ENCJA" + encja.toString());
return encja;
}finally{
db.close();
}
and I got it (picture below) - string field "abstrakt" is null now !!!
I take a look at it using ObjectManager (picture below) and abstrakt field has not-null value there!!! The same value, that on the 1st picture.
Please help me :) It is my second day with db4o. Thanks in advance!
I am attaching some code with structure of persisted class:
public class EncjaDanych{
Map mapaIdRepo = new HashMap();
public Map mapaNazwaRepo = new HashMap(); }
!!!!!!!!UPDATED:
When I tried to read only Metadane object (there was only one such a object), it is all right - it's string field abstrakt could be read correctly.
try{
Query q = db.query();
q.constrain(Metadane.class);
ObjectSet<Object> objectSet = q.execute();
logger.error("objectSet.size" + objectSet.size());
Metadane meta = (Metadane) objectSet.get(0);
logger.debu("Metadane" + meta.toString());
return meta;
}finally{
db.close();
}
This is a common db4o FAQ, an issue with what db4o calls "activation". db4o won't instantiate the entire graph you stored when you load an object from an ObjectContainer. By default, objects are instantiated to depth 5. You can change the default configuration to a higher value, but that is not recommended since it will slow down object loading in principle because the depth will be used everywhere you load an object with a query.
Two approaches are possible to solve your issue:
(1) You can activate an object to a desired depth by hand when you need a specific depth.
db.activate(encja, 10) // 10 is arbitrary
(2) You can work with Transparent Activation. There are multiple chapters on how to use Transparent Activation (TA) in the db4o tutorial and in the reference documentation.
You're not setting a filter in your query so you're reading the first object. Are you sure you didn't have a previous object in the database?

Resources