I've been looking around and around without finding any topics related to my situation.
I'm using:
Play! framework v2.5.3 in Java
Hibernate EntityManager v5.1.0.Final
Hibernate JPA 2.1 API v1.0.0.Final
PostgreSQL 9.4
Here the route called with AJAX:
PUT /admin/entity/:id
Which is bound to:
controllers.Entity.update(id: Long)
Here how I handle the update request:
#play.db.jpa.Transactional
public Result update(final long id) {
EntityManager em = _jpa.em("default");
DynamicForm form = _formFactory.form().bindFromRequest();
models.Entity entity;
entity = em.find(models.Entity.class, id);
if (entity == null)
return badRequest();
entity.update(em, form);
em.merge(entity);
return ok();
The method update of Entity change values of the class attributes which are basically String attributes.
My issue: nothing get updated while still executing this piece of code.
I enable SQL log which only display the SELECT query corresponding to em.find() method call. Nothing related to an UPDATE query.
I've been using JPA/EntityManager with Play! for others projects (but with lower version of the framework) without facing this kind of problem.
Any idea why nothing get merged ?
I've been able to fix this issue by writing following piece of code inside
models.Entity.update:
em.getTransaction.begin();
Query query = em.createQuery("UPDATE entity SET value = :v WHERE id = :id");
query.setParameter("value", value);
query.setParameter("id", id);
query.executeUpdate();
em.getTransaction.commit();
But even if this is working, that's not the way how thing should be done... It
doesn't make coffee at all!
Edit: this solution do not work anymore....
I really don't know what I'm doing bad, if any body has an idea about this issue, you're help would be much appreciated.
Related
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...
In play framework, I use following code to fetch values from a table called "Report" which has other relationship tables like "Project","Build" etc.
List<Report> rpts = Report.find.where()
.eq("publish","1")
.eq("functionality_id", Integer.toString(fun.id))
.eq("project_id", currentProject.id)
.eq("prod_build", prod_build)
.eq("loadType_id", loadType_id)
.in("build_id", buildId)
.orderBy("id desc")
.findList();
I get list of values from "Report" table, but all related table values are not populated. They are populated with null.
#Entity
#Table(name="report")
public class Report {
#Id
public int id;
#Constraints.Required
#ManyToOne
#JoinColumn(name="build_id")
public Build build;
#Constraints.Required
#ManyToOne
#JoinColumn(name="project_id")
public Project project;
.
.
}
It was loaded with those values when I tested couple of days ago, but not working today. When I do rpts.get(i).build.release , it gives nullPointerException because build is null here. This code has not been changed in recent days. Wondering why this is happening. Can someone suggest me whether there is any other setting file (like application.conf) that does this lazy loading. Please help.
I've resolved it.
The problem is that I created an Ebean transaction using following code that caused the trouble.
Ebean.beginTransaction();
try{
group.role = "A";
Ebean.update(group);
Ebean.commitTransaction();
} finally {
Ebean.endTransaction();
}
I never suspected that this could would have caused the problem as I put this code in another class file that is not related to this page. Then I changed to following code and everything worked as expected.
#Transactional
public void saveGroup(Group group){
group.role = "A";
Ebean.save(group);
.
.
}
Following documentation in play framework site helped me to identify the culprit. :)
Enhancement of direct Ebean field access (enabling lazy loading) is
only applied to Java classes, not to Scala. Thus, direct field access
from Scala source files (including standard Play 2 templates) does not
invoke lazy loading, often resulting in empty (unpopulated) entity
fields. To ensure the fields get populated, either (a) manually create
getter/setters and call them instead, or (b) ensure the entity is
fully populated before accessing the fields.
We have a web application with Entity Framework 4.0. Unfortunately, when the large volume of users hit the application the EF throws an error
The underlying provider failed on Open
Below is the code snippet:
//DAL
public IQueryable<EmployeeEntity> GetEmployeeDetail()
{
DatabaseEntities ent = new DatabaseEntities(this._connectionString);
IQueryable<EmployeeEntity> result = from employee in ent.EmployeeEntity
select employee;
return result;
}
Please note the above code returns IQuerable.
Is anything wrong with above pattern that could cause the exception to occur?
When and how does Entity Framework determine to close / open db connection and also how long to retain?
On what scenario does above error occurs?
What's the maximum number of connection pool for EF and how do we configure?
Do we need to explicitely specify open and close
Is code below a best way to resolve above issue?
public IQueryable<EmployeeEntity> GetEmployeeDetail()
{
using (DatabaseEntities ent = new DatabaseEntities(this._connectionString))
{
IQueryable<EmployeeEntity> result = from employee in ent.EmployeeEntity
select employee;
return result.ToList().AsQuerable();
}
}
The ToList() call will cause the query to run on the database immediately and as this is not filtered in any way will return every employee in your database. This is probably likely to cause you performance issues.
However you can't remove this in your case because if you return the IQueryable directly then the context will be disposed by the time you try and fetch results.
You could either:
change the way it works so that the scope of ent does not end when the method returns and return the query without calling ToList(). You can then further filter the IQueryable before calling ToList().
call ToList() within the method but filter/limit the query first (e.g. pass some parameters into the method to specify this) to reduce the number of rows coming back from the database.
I have created Generic Repository and I have two entities that i need to update in a transaction.
Here is what i m doing..
ProductOrganizationEntity poDataContext= new ProductOrganizationEntity();
IRepository<tblProductInfo> productRepo = new GenericRepository<ProductOrganizationEntity, tblConfirmation>(poDataContext);
Piece of Code which is causing problem is this.
using (TransactionScope txScope = new TransactionScope())
{
productRepo.Attach(productEntity);
productRepo.SaveChanges();
new ProductLocation().SaveLocation(productEntity.Locations, productEntity.productCode);
txScope.Complete();
}
productRepo.SaveChanges(); This is where it throws me Error. The error is
The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "Venus" was unable to begin a distributed transaction.
(We do have server named Venus but its not access in anyway in these transactions at all. Secondly as i said this works without transaction block).
This piece of code works fine if taken out from Transaction Block.
ProductLocation.SaveLocation is creating Repository for Location . Here is the code from Save Location.
IRepository<LocationInfo> locRepo= new GenericRepository<ProductOrganizationEntity, LocationInfo>(new ProductOrganizationEntity());
if (loc.locID <= 0) // This is a new Location to be added.
locRepo.Add(locEntity);
else
locRepo.Attach(siteToAdd);
locRepo.SaveChanges();
Here is what i have done in my generic repository for thse methods
public void Attach(TEntity entity)
{
if (entity == null)
throw new ArgumentException("Update : Supplied Entity is Null.");
_currentDbSet.Add(entity);
System.Data.Entity.Infrastructure.DbEntityEntry entry = _dataContext.Entry(entity);
entry.State = System.Data.EntityState.Modified;
}
and this is what i have in SaveChanges in my generic repo.
public virtual void SaveChanges()
{
if (_dataContext == null)
throw new Exception("SaveChanges: DataContext is not initialized.");
_dataContext.SaveChanges();
}
What is that i am doing wrong here .
I appreciate any pointers.
It might be possible that your server is linked to another SQL server at the database level.
Perhaps look at this: http://msdn.microsoft.com/en-us/library/ms188279.aspx
Must admit I've never used linked servers (not yet at least), but seeing "Linked Servers" in the error made me think of this.
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.....