I have the following code which I call from the front end
public Login update(Login i) {
em = emf.createEntityManager();
em.getTransaction().begin();
Login result=infoDAO.update(i);
em.getTransaction().commit();
em.close();
return result;
}
public Login update(Login i) {
return em.merge(i);
}
I have
private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("HRTool-JPA");
protected EntityManager em=emf.createEntityManager();
The methods are being called and the values are passed to the DB correctly(I am using Apache derby) but I can see the new changed values in the DB only after I disconnect and reconnect to it. Am I missing some step after merge ? I am new to JPA and appreciate any suggestions on the same
By default Hibernate keep the requests in its cache and Hibernate decides when it wants to execute them.
You can try to add a em.flush() after em.merge()
It will execute all the requests left in its cache.
Related
I am Using Spring Data Jpa and adding inserting into 2 table when something happen while adding into second table the first transaction is not rollbacking
and first insert is commiting immidiatally after insert
#Override
#Transactional(propagation = Propagation.REQUIRED, rollbackFor =
Exception.class)
public void addVehicleType(Map<String, Object> model)throws Exception {
VehicleType vehicleType = null;
VehicleStatus vehicleStatus = null;
try {
vehicleType = (VehicleType) model.get("vehicleType");
vehicleStatus = (VehicleStatus) model.get("vehicleStatus");
vehicleStatusRepository.save(vehicleStatus);
vehicleTypeRepository.save(vehicleType);
} catch (Exception e) {
throw e;
}
VehicleTypeRepository.java
public interface VehicleTypeRepository extends JpaRepository<VehicleType, Long> {
#Override
void delete(VehicleType role);
long count();
}
If you use mysql, you must have InnoDB Engine.
Second, problem could be if you are testing on local pc.
Uncomment in my.ini default_tmp_storage_engine=MYISAM
; The default storage engine that will be used when create new tables
; default-storage-engine=MYISAM
; New for MySQL 5.6 default_tmp_storage_engine if skip-innodb enable
default_tmp_storage_engine=MYISAM
The only exceptions that set a transaction to rollback state by default are the unchecked exceptions (like RuntimeException).
Please note that the Spring Framework's transaction infrastructure code will, by default, only mark a transaction for rollback in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException. (Errors will also - by default - result in a rollback.) Checked exceptions that are thrown from a transactional method will not result in the transaction being rolled back.
I am implementing a feature where if there is any exception while writing data into DB, we should retry it for 5 times before failing. I have implemented the feature but not able to test it using arquillian test.
We are using JPA and Versant as database. Till now, I am debbuging the the arquillian test and once my flow reaches DB handler code, I am stopping the database. But this is worst way of testing.
Do you have any suggestion how to achieve the same ?
With JPA in mind, the easiest way is to add method to your data access layer, with which you are able to run native queries. Then you run query against nonexisting table or something similar. So in my DAO utilities I found method like this:
public List findByNativeQuery(String nativeQuery, Map<String, Object> args) {
try{
final EntityManager em = getEntityManager();
final Query query = em.createNativeQuery(nativeQuery);
if (args!=null && args.entrySet().size()>0) {
final Iterator it = args.entrySet().iterator();
while (it.hasNext()) {
final Map.Entry pairs = (Map.Entry)it.next();
query.setParameter(pairs.getKey().toString(), pairs.getValue());
}
}
return query.getResultList();
}
catch (RuntimeException e) {
// throw some new Exception(e.getMessage()); // the best is to throw checked exception
}
}
Native solutions
There is the old trick by dividing by zero in the database. At the time of selection you could try:
select 1/0 from dual;
Insertion time (you need a table):
insert into test_table (test_number_field) values (1/0);
pure JPA solution
You can try to utilize the #Version annotation and decrement it to throw OptimisticLockException. This is not thrown in the database, but in the Java layer, but fullfills your need.
Those all will result in DB fail.
I am updating an application. I have replaced most of the queries in the app with calls to ejbs but the code below calls a huge procedure and it would be almost impossible to re-write.
I would like to return an ejb to the result set R but I have not been able to figure this out....
java.sql.ResultSet R = Cmd.executeQuery("SELECT * FROM TableData");
String[] Names = {"id","Project","Resource","Week","Hours"};
out.print(getTableXML(R,Names));
R.close();
My ejb:
public List<Gridmaster> getDisplayGridList() {
return em.createQuery("FROM Gridmaster order by gridid", Gridmaster.class).getResultList();
Is this possible or do I need to create an old style db connection?
Thanks for any help.
First I want to explain my self-invoked ejb method in this situation. I have a stateful session bean with a method which starts a new transaction (Annotated by #REQUIRES_NEW). To invoke this method inside the bean itself and make the annotation effective, I use SessionContext#getBusinessObject() to achieve the effect of #EJB (#EJB here causes stackoverflow?!). My code is shown below:
#Stateful
#Local
public class TransactionTest implements ITransactionTest {
#PersistenceContext(unitName="Table",Type=PersistenceContextType.EXTENDED)
private EntityManager manager;
#Resource
SessionContext sc;
ITransactionTest me;
#PostConstruct
public void init(){
me = this.sc.getBusinessObject(ITransactionTest.class);
}
public void generateRecord(int i) throws RuntimeException{
Record record = new Record();
record.setId(i+"");
record.status(1);
manager.persist(record);
manager.flush(); //If not flush, result is correct. Why?
me.updateRecord(i);
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void updateRecord(int i) throws RuntimeException{
try {
Record record = manager.find(Record.class, i+"");
record.setStatus(2);
manager.flush();
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
While,generateRecord() runs properly. The console shows it executes 'insert' and 'update' HQL without any exception (I use Hibernate as JPA provider). However, the 'update' result doesn't appear in the database. Why? Does updateRecord() commit correctly?
Also, I try it in two altenative ways: First is invoking generateRecord() (it will no longer invoke updateRecord()) and updateRecord() consecutively in another bean. It can give me the right result.
The second is removing the first flush(). Then both 'insert' and 'update' HQL will be executed at the second flush(). This method can also produce right result.
My program is running under JBOSS 6.1.0-Final and database is Oracle.
Best Regards,
Kajelas
I'm trying to delete all database entries for a Spring Roo entity. When I look at *_Roo_Entity.aj it seems as if there is no "delete all" method. I tried to implement it myself (Licences is the name of the Roo entity. Don't mind the naming. It was reverese engineered from a database and may be changed later):
public static int Licences.deleteAll() {
return entityManager().createQuery("delete from Licences o").executeUpdate();
}
It compiles just fine but when I call Licences.deleteAll() I get the following exception:
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query;
nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query (NativeException)
Adding #Transactional doesn't make a difference.
What am I missing here?
Is this approach completely wrong and I need to implement it like this:
public static void Licences.deleteAll() {
for (Licences licence : findAllLicenceses()) {
licence.remove();
}
}
This works, but is JPA smart enough to translate this into a delete from licences query or will it create n queries?
#Transactional doesn't work on static function
change
public static int Licences.deleteAll() {
return entityManager().createQuery("delete from Licences o").executeUpdate();
}
to
public int Licences.deleteAll() {
return entityManager().createQuery("delete from Licences o").executeUpdate();
}
https://jira.springsource.org/browse/SPR-5999
Bye
JPA does not have a delete all functionality. (even not with JQL!)
At least there are only three ways:
The loop, like you did
A JPQL Query see: JPQL Reference: 10.2.9. JPQL Bulk Update and Delete
A native SQL Query, but this will cause many problems with Entity Manager caches!
BTW: It seams that you are using AspectJ to attach you delete method. - You can do this (even if I do not know, why not adding the static method direct to the Entity class), but you must not touch the Roo generated aj files!
public static int Licences.deleteAll() {
return new Licences().deleteAllTransactional();
}
#Transactional
private int Licences.deleteAllTransactional() {
if (this.entityManager == null) this.entityManager = entityManager();
return this.entityManager.createQuery("delete from Licences o").executeUpdate();
}