I use JPA to add data to Derby DB with eclipse link and when there is duplicated ID.
I got error, there is a way in run-time (with code) to simple delete all the table entries.
I don't need the old entry just new entries in every time that I invoke the program.
I tried with
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();
Query query = entityManager.createQuery("SELECT p FROM Job p ");
List resultList = query.getResultList();
for (Object result : resultList) {
entityManager.remove(result);
}
entityManager.getTransaction().commit();
entityManager.close();
but here I use query before and I don't want to do that I want to delete all the entries and I don't care what is there before.
You can use the SQL DELETE query at runtime everytime the application starts. If you don't post some code, we can't help.
EDIT :
You can execute the query as follows in some earlier transaction or the same transaction before the query:
int deletedCount = entityManager.createQuery("DELETE FROM Job").executeUpdate();
You could either execute a delete query, or configure your persistence unit to recreate the tables when the persistence unit is deployed.
See,
http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_ddl_generation.htm#BABHEJJI
Related
I have a Java spring boot project and I use Hibernate in this project. I have a void deleteAll(List<Long> idList) method and its query is #Query(value = "DELETE c FROM Course c WHERE c.id in :idList", nativeQuery = true). I want to use a trigger after every delete operation. I created a trigger in mysql and it works when I try in mysql, but it doesn't work when I call void deleteAll(List<Long> idList) method. How can use my trigger with hibernate?
My trigger defination:
DELIMITER $$
CREATE TRIGGER after_delete_course AFTER DELETE ON course FOR EACH ROW
BEGIN
DELETE tc1 FROM table1_course tc1 WHERE tc1.course_id = OLD.id;
DELETE tc2 FROM table2_course tc2 WHERE tc2.course_id = OLD.id;
DELETE tc3 FROM table3_course tc3 WHERE tc3.course_id = OLD.id;
END$$
DELIMITER ;
SQL generated by hibernate when deleteAll is called :
Hibernate:
DELETE c
FROM
Course c
WHERE
c.id in (
?
)
How do you know it doesn't work? You won't see the delete queries of your trigger being logged in your application, this is happening only on the DBMS side.
If you have an EntityManager that contains the deleted entity or the associations deleted by the trigger, you will have to detach them from the EntityManager to get a consistent view again, as Hibernate does not know what effects DML statements will have on the managed entities. Try using EntityManager.clear after executing this DML statement.
An alternative solution is to use the entity lifecycle annotations provided by JPA.
In this case, you are performing a delete operation. So, you can use the #PreRemove annotation.
You can check some examples on Baeldung
I have Document entity and some managed document object for doc with id=1.
Document managedDoc = entityManager.find(Document .class, 1);
managedDoc.setName("changedName");
As I know, managed doc state changed in persistent context (futher PC) after calling setter but nothing changed in database. Somewhere in my code I do the following:
Query query = entityManager.createQuery("from Document");
List<Document> list = query.getResultList();
return list;
When I perform select-all query as shown above, is document with id=1 taken from DB or from PC? From DB means select will not see new name because new name still in PC.
Actually, my problem is in updating via merge() and flush() and futher retrieving all objects - currently my select-all query doesn't see new values of some fields. Looks like merge+flush is OK, but JPA Query reads not from DB but from PC. But even if I'm right, both PC and DB contains new value of the name, why my select-all doesn't see it?
Moreover, select all sometimes returns correct/updated values, sometimes not
UPDATE
Clarification:
I put some object to PC via entityManager.find(Document .class, 1);
I create new detached instance with some name property setted. Id and other props gotten from managed instance. For example,
managedDoc = getFromSomeDataStructure();
Document nonManaged = new Document(managedDoc.getId()); nonManaged.setName("newName");
I update DB via em.merge(nonManaged);flush();
I saw my changes in DB when check it in Workbench.
I'm pressing F5 (and even CTRL+F5) button which performs select-all JPQL query and on each odd button press==select-all query I see non-actual old value, on each even button press==select-all query I see correct value.
It will be taken from the Persistent Context, as long as it has them their. To be more correct: as long as you have an entity in a managed state (i.e in the Persistence Context), it will not be overrriden. Of course, in the context when the same EntityManager instance is used.
If you want to refetch the value from DB, you have different possibilities:
Use another EntityManager, in a different transaction (important!).
Use EntityManager.detach() or if you want to clear the entire persistence context, use EntityManager.clear()
Use EntityManager.refresh() to throw out all changes made to an entity instance.
Let me try to clarify with a couple of examples an maybe this answer your question or with luck, helps to make the question clearer.
Scenario #1: Two Different Reads
Department department = em.find(Department.class, 1);
department.setName("Jedi Masters");
TypedQuery<Department> typedQuery = em.createQuery("SELECT d FROM Department d", Department.class);
List<Department> departments = typedQuery.getResultList();
for(Department found : departments){
if(found.getId().equals(1)){
assert found == department;
assert found.getName().equals(department.getName());
}
}
In this first scenario you can expect the department and found to be exact same instance and therefore have the exact same values. Both assertions above pass.
Scenario #2: Merging Detached Entity
//detached entity
Department department = new Department();
department.setId(1);
department.setName("Jedi Masters");
em.merge(department);
TypedQuery<Department> typedQuery = em.createQuery("SELECT d FROM Department d", Department.class);
List<Department> departments = typedQuery.getResultList();
for(Department found : departments){
if(found.getId().equals(1)){
assert found != department);
assert found.getName().equals(department.getName());
}
}
At least with Hibernate, the behavior in this case is slightly different. The two objects are not the same instance. They are different instances, but they still should have the same contents.
So, depending on your implementation on how you are comparing them you might get unexpected results, above all if you do not implemented a right equals/hashCode protocol for detached cases like this.
As answered here, I should call refresh() for each item in result list. But only refreshing didn't work for me. After setting READ COMMITED in persistence.xml by writing
<property name="hibernate.connection.isolation" value="2" />
everything worked perfectly.
P.S Don't forget to mark select method as #Transactional because refresh() doesn't work without this annotation.
I am using Hibernate 4.2.4 and I am interested to know how Hibernate translate a session.get call to an equivalent sql query that is eventually used to retrieve rows from database. I do not want to log the generated sql in console. I want to use the same sql query in my application. Something like below.
...
SessionFactory sessionFactory = configuration.buildSessionFactory(builder.buildServiceRegistry());
// I want the query string here
String query = sessionFactory.someUnknownMethod(Some Paramters);
Session session = sessionFactory.openSession();
// actual session.get query
Comment comment = (Comment) session.get(Comment.class, new Integer(1));
...
I have seen this thread for Criteria query -> How to get SQL from Hibernate Criteria API (*not* for logging).
I would like to know if similar procedure exists for session.get type queries.
I have also seen this thread -> get SQL from hibernate get
where the question is exactly same as mine, but the accepted solution talks about fetching statistics which, to my understanding, only accounts for the queries that have already been executed. Plus, from statistics I was able to catch hql/sql queries but not session.get queries.
I want to know if there is a way for a user to generate and use the sql even before the actual session.get gets executed (possibly by following the same path as hibernate).
im familiar with this following way to delete the data (just the data ,not the entity itself)
from the entity
entityManager.getTransaction().begin();
entityManager.createQuery("DELETE FROM " + className)
.executeUpdate();
entityManager.getTransaction().commit();
there is another way to do that like to provide the entityname and then reomve all the data .
You're not using SQL in your code but JPQL, JPA Query Language.
There is no other way to delete all data at once, except by loading all of them and deleting them one by one. It's not even possible with criteria queries since they don't support delete operation yet.
Well.. in this case both NativeSQLQuery and JPQL resolve to the same thing. What you did is JPQL way. The following you could write a nativeSQLQuery
EntityManager em = ...;
Query query = em.createNativeQuery ("SELECT * FROM EMP", Employee.class);
I'm trying to use JPA with HibernateSearch. I used Example 5.3 in http://docs.jboss.org/hibernate/stable/search/reference/en/html/search-query.html. The results come out as expected.
However, the data coming back is a huge graph. I only need the primary key of the data. So, I tried Example 5.9, but it only shows the Hibernate API. There was not a javax.persistence.Query.setProjection() method.
What can I use to get just the primary key of a search result? Should I try to get the hibernate session from the EntityManager in JPA?
Thanks for any help.
Example 5.3 was a bit misleading. javax.persistence.Query doesn't have to be used. Instead, org.hibernate.search.jpa.FullTextQuery has the setProjection() method that I needed. Here is the resulting code (with fully qualified class names):
//Open JPA session
javax.persistence.EntityManagerFactory emf=javax.persistence.Persistence.createEntityManagerFactory("manager1");
javax.persistence.EntityManager em=emf.createEntityManager();
em.getTransaction().begin();
//Make a FullText EM from the JPA session.
org.hibernate.search.jpa.FullTextEntityManager fullTextSession=org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
//Build the lucene query.
org.apache.lucene.queryParser.QueryParser parser=new org.apache.lucene.queryParser.QueryParser("data1",new org.apache.lucene.analysis.standard.StandardAnalyzer());
org.apache.lucene.search.Query query=parser.parse("FindMe");
//Convert to a hibernate query.
org.hibernate.search.jpa.FullTextQuery query2=fullTextSession.createFullTextQuery(query, SampleBean.class);
//Set the projections
query2.setProjection("id");
//Run the query.
for (Object[] row:(List)query2.getResultList()){
//Show the list of id's
System.out.println(row[0]);
}
//Close
em.getTransaction().commit();
em.close();
emf.close();
query2 does the projection and all is well!