EclipseLink cache refreshOnlyIfNewer not working - jpa

I'm trying to use cache with EclipseLink.
I've enabled shared-cache-mode = ENABLE_SELECTIVE in my persistence.xml so when I use #Cacheable(true) the entity gets cached. Now I want make it work when the version is outdated the the enity gets refreshed.
I've setup a optimistic locking field
#Version
#Column(name="optLock")
private int versionNum ;
this is working when as when I try to save an entity that has a older version number then the database I'll get an exception.
So when I add the annotation to enable caching and refresh
#Cacheable(true)
#Cache(size = 500, alwaysRefresh = true, refreshOnlyIfNewer = true)
the entity won't be cached. I've enabled the eclipselink.profiler and I can see that no cache is made for this entity and lacking the Counter:CacheHits and Counter:CacheMisses log.
When I remove
#Cache(size = 500, alwaysRefresh = true, refreshOnlyIfNewer = true)
the entity is cached again but any changes done directly in the database(and increment the optLock field) won't come through.
What I forgetting her? or what should I take into account to get this working? The documentation I've been reading seems like this should be working.

#Cache overrides #Cacheable, so because you did not enable caching in #Cache it gets the persistence unit default of not caching.
Add,
#Cache(isolation=SHARED, ...)
to your annotation.
Please also log a bug, EclipseLink should be smart enough to see the #Cacheable and use it as the default because there was no isolation setting in the #Cache, or at least report a warning.

Related

MongoDB unique index allows duplication

I am new in mongoDb and I have a problem with mongock. Previously I had an index defined by annotation like below. In my unit test I have a case which tries to save same value on the same field and it throws exception as expected.
#Indexed(unique = true)
private String name;
I removed #Indexed annotation and I created index by mongock migration. But in this time I am able to insert a record with same value for this column without getting exception. So what is wrong here and why it is not working as it works above. I created my migration as :
collection.createIndex(
new Document(new ImmutableMap.Builder<String, Object>()
.put("name", 1)
.build()),
new IndexOptions().name("name_idx").unique(true),
);
Without providing information about the version you are using, it's hard to say.
However I believe your issue can be related to an old existing bug.
Please use the last version 4.0.8.alpha, which is alpha as features are still being added, but very stable(there is no official documentation yet, but you can see the sample project here) or the last official stable version: 3.3.2.
Please notice that in both case you should use MongockTemplate, instead of MongoTemplate.
I believe that will solve your issue. Otherwise, please provide version and stack trace.

prolems with DB "save" with #LastModifiedDate and #LastModifiedBy

I've setup Spring Data JPA Auditing as it is described in the docs. I think its configured correctly because on insert, i have all 4 fields (created, createdBy, modified, modifiedBy) filled in correctly.
Now the interesting part. On modification of the entity, everything seems to be running well. I debugged through all the Spring Auditing classes up to the point where in AuditingHandler.java this line:
LOGGER.debug("Touched {} - Last modification at {} by {}", new Object[] { target, defaultedNow, defaultedAuditor });
Looks completely ok. The target has the modified Fields set correctly and i cant see any issues BUT in the database, the two fields wont get updated. (value is still the creation date and user). So somehow it wont get saved. Of course all the other fields get updated including the JPA Version field. So everything but the modified* fields.
I am clueless. Anyone who can help me further how to debug that?
I am using Spring-Data-JPA in 1.9.0 and Spring 4.2.1 together with OpenJPA in the persistence backend.
UPDATE
I think i pinpointed the problem but there is a bug either in OpenJPA oder Spring-Data JPA.
The following class BeanWrapper.java from Spring-Data runs this code:
/*
* (non-Javadoc)
* #see org.springframework.data.mapping.PersistentPropertyAccessor#setProperty(org.springframework.data.mapping.PersistentProperty, java.lang.Object)
*/
public void setProperty(PersistentProperty<?> property, Object value) {
Assert.notNull(property, "PersistentProperty must not be null!");
try {
if (!property.usePropertyAccess()) {
ReflectionUtils.makeAccessible(property.getField());
ReflectionUtils.setField(property.getField(), bean, value);
return;
}
Method setter = property.getSetter();
if (property.usePropertyAccess() && setter != null) {
ReflectionUtils.makeAccessible(setter);
ReflectionUtils.invokeMethod(setter, bean, value);
}
} catch (IllegalStateException e) {
throw new MappingException("Could not set object property!", e);
}
}
JpaPersistentPropertyImpl (property) has usePropertyAccess attribute set to false, thus changing the modified field directly via reflection but this wont get the attribute marked dirty in OpenJPA. When modifying the value to true in the debugger, forcing to use the setter(), everything works fine.
So somewhere is a problem with the way OpenJPA <-> Spring Data interaction. Seems that OpenJPA doesnt like reflection attribute changes and insists on setter().
Is there a way to get this usePropertyAccess property to true?
CONCLUSION
Every journey needs to end. I found out that using #AccessType(AccessType.Type.PROPERTY) on my modified*/created* fields solves the issue. I am not quite sure that the current default -> AccessType.Type.Field is the most sensible one in Spring-Data... at least its not for OpenJPA. IMO this one is pretty hard to to find for non-experienced JPA/Spring developers. Perhaps a note in the documentation would be helpful. I have never used this AccessType property in my life and i am using Spring with OpenJPA for quite some time...

How to make EF log sql queries globally?

How do I "tell" EF to log queries globally? I was reading this blog post: EF logging which tells in general how to log sql queries. But I still have a few questions regarding this logger.
Where would I need to place this line context.Database.Log = s =>
logger.Log("EFApp", s);?
Can it be globally set? Or do I have to place it everywhere I do DB
operations?
In the "Failed execution" section, the blogger wrote that, and I
quote:
For commands that fail by throwing an exception, the output contains the message from the exception.
Will this be logged too if I don't use the context.Database.Log?
Whenever you want the context to start logging.
It appears to be done on the context object so it should be done every time you create a new context. You could add this line of code in your constructor though to ensure that it is always enabled.
It will not log if you do not enable the logging.
I don't recommend to use that's functionality, because, it hasn't reason to exists in the real case.
Thats it use a lot of to debug code only. But, wether you wanna know more than details ... access link... https://cmatskas.com/logging-and-tracing-with-entity-framework-6/
In this case you can put code like this
public void Mylog()
{
//Thats a delegate where you can set this property to log using
//delegate type Action, see the code below
context.Database.Log = k=>Console.Write("Any query SQL")
//Or
context.Database.Log = k=>Test("Any query SQL")
}
public void Test(string x){
Console.Write(x)
}
I hope thats useufull

Update a table using JPA in Play Framework

I'm trying to update a table using JPA
EntityManager em=JPA.em();
EntityTransaction entr = em.getTransaction();
try{
if(!entr.isActive())
entr.begin();
Tblrecordtypefields updateTblrecordtypes = em.find(Tblrecordtypefields.class,9);
updateTblrecordtypes.setFieldlabel("JPATest");
em.getTransaction().commit();
}finally
{
if(entr.isActive())
entr.rollback();
}
i'm getting the error
NullPointerException occured : null at
updateTblrecordtypes.setFieldlabel("JPATest");
What should i do.
I see some possible issues in there:
First, Play manages the transactions on it's own. A transaction is created at the beginning of the request and committed (rollback if exception) at the end. You are trying to force your way into it, that's not recommended. To manage the entity, just do an entity.save() to mark it as "to be saved" and don't do tht to ignore any changes.
Second, if you are using the Model class in Play (as you should) you can use the "find" and "findById" methods provided by this class. This is recommened, instead of using the EntityManager directly.
See the documentation for more information.
Basically, redo your code to follow the Play way, to avoid problems :)
EDIT: as a clarification, I'm not really answering your question on why you get the NPE, but I think that as you are forcing your way into the settings of the framework you might (maybe not!) be seeing unexpected artifacts that will dissapear once you fix your code to follow convention.
If after that you still have the error let us know :)
This means that there is no row with ID 9 in the database table mapped by the entity Tblrecordtypefields.
BTW: I find it very questionable to commit a transaction in a method which is not necessary the one that started the transaction.
I have changed my code as below
Tblrecordtypefields updateTblrecordtypeFields = Tblrecordtypefields.findById(9);
updateTblrecordtypeFields.setFieldlabel("Test");
validation.valid(updateTblrecordtypeFields);
if(validation.hasErrors())
{
updateTblrecordtypeFields.refresh();
}
else
{
updateTblrecordtypeFields.save();
}
in my model class
public void setFieldlabel(String fieldlabel) {
this.fieldlabel = fieldlabel;
}
Works Fine.....

EF 4 Self Tracking Entities does not work as expected

I am using EF4 Self Tracking Entities (VS2010 Beta 2 CTP 2 plus new T4 generator). But when I try to update entity information it does not update to database as expected.
I setup 2 service calls. one for GetResource(int id) which return a resource object. the second call is SaveResource(Resource res); here is the code.
public Resource GetResource(int id)
{
using (var dc = new MyEntities())
{
return dc.Resources.Where(d => d.ResourceId == id).SingleOrDefault();
}
}
public void SaveResource(Resource res)
{
using (var dc = new MyEntities())
{
dc.Resources.ApplyChanges(res);
dc.SaveChanges();
// Nothing save to database.
}
}
//Windows Console Client Calls
var res = service.GetResource(1);
res.Description = "New Change"; // Not updating...
service.SaveResource(res);
// does not change anything.
It seems to me that ChangeTracker.State is always show as "Unchanged".
anything wrong in this code?
This is probably a long shot... but:
I assume your Service is actually in another Tier? If you are testing in the same tier you will have problems.
Self Tracking Entities (STEs) don't record changes until when they are connected to an ObjectContext, the idea is that if they are connected to a ObjectContext it can record changes for them and there is no point doing the same work twice.
STEs start tracking once they are deserialized on the client using WCF, i.e. once they are materialized to a tier without an ObjectContext.
If you look through the generated code you should be able to see how to turn tracking on manually too.
Hope this helps
Alex
You have to share assembly with STEs between client and service - that is the main point. Then when adding service reference make sure that "Reuse types in referenced assemblies" is checked.
The reason for this is that STEs contain logic which cannot be transfered by "Add service reference", so you have to share these types to have tracing logic on client as well.
After reading the following tip from Daniel Simmons, the STE starts tracking. Here is the link for the full article. http://msdn.microsoft.com/en-us/magazine/ee335715.aspx
Make certain to reuse the Self-Tracking Entity template’s generated entity code on your client. If you use proxy code generated by Add Service Reference in Visual Studio or some other tool, things look right for the most part, but you will discover that the entities don’t actually keep track of their changes on the client.
so in the client make sure you don't use add service reference to get the proxy instead access service through following code.
var svc = new ChannelFactory<IMyService>("BasicHttpBinding_IMyService").CreateChannel();
var res = svc.GetResource(1);
If you are using STEs without WCF you may have to call StartTracking() manually.
I had the same exact problem and found the solution.
It appears that for the self-tracking entities to automatically start tracking, you need to reference your STE project before adding the service reference.
This way Visual Studio generates some .datasource files which does the final trick.
I found the solution here:
http://blogs.u2u.be/diederik/post/2010/05/18/Self-Tracking-Entities-with-Validation-and-Tracking-State-Change-Notification.aspx
As for starting the tracking manually, it seems that you do not have these methods on the client-side.
Hope it helps...