I want to know if I can perform em.remove for each element in that local list? Does this code changes state in DB?
TypedQuery<Product> query = em.createNamedQuery("Product.findByCode", Product.class);
query.setParameter("code", code);
List<Product> productList= query.getResultList();
for (int i = 1; i < productList.size(); i++) {
em.remove(productList.get(i));
}
Yes it changes the DB, since that is his job.
The EntityManager API is used to create and remove persistent entity instances, to find entities by their primary key, and to query over entities.
https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html
Related
I was successfully able to execute a jpql query and print the result which is stored in a queryResults variable. What I want to achieve next is storing just the IDs (primary key column) in a list without the date (value), but I am not too sure if this is possible; perhaps using something like a java map. Is it possible? If yes, how can this be easily achieved?
private static final TestDao Test_DAO = new TestDao();
#Test
public void testById() {
List<TestEntity> queryResults = TEST_DAO.findById(""); //The record from the sql query is stored in queryResults and findById("") is the method that executes the query in a TestDao class and it is called here
for (TestEntity qResult: queryResults) { // looping through the query result to print the rows
System.out.println(qResult.getId());
System.out.println(qResult.getDate());
}
System.out.println("This is the sql result " + queryResults );
}
Output:
This is the result [TestEntity(id=101, date=2020-01-19 15:12:32.447), TestEntity(id=102, date=2020-09-01 11:04:10.0)]// I want to get the IDs 101 and 102 and store in a list without the Dates
I tried using a map this way:
Map<Integer, Timestamp> map= (Map<Integer, Timestamp>) queryResults.get(0); but I got an exception:
java.lang.ClassCastException: TestEntity cannot be cast to java.util.Map
There are some points before the implementation.
Why are you defining DAO as static? I think this is a bad implementation unless I am missing a particular reason you declared it static. You should define this as a member variable and not a static member
The naming of the method - findById() translated in English is - find Something by this Id, but you are fetching a list of Records, so naming is not correct.
Point 2 becomes invalid if ID property is not a Primary Key in your table, then it makes sense, but still naming is bad. Id is something we use to define Primary Key in the Database and should be and will be unique. But your comments suggest that ID is unique and the Primary Key. So read about how Databases work
And even if not unique, if you pass an Id to find some records, why will get different ids in the Records !!!
About implementation:
Changing in your existing code:
private TestDao Test_DAO = new TestDao();
#Test
public void testById() {
List<TestEntity> queryResults = TEST_DAO.findById("");
List<Long> listOfIds = new ArrayList<>(); // Assuming Id is Long type, same logic for any type
for (TestEntity qResult: queryResults) {
System.out.println(qResult.getId());
listOfIds.add(qResult.getId()); // Just add it to the list
System.out.println(qResult.getDate());
}
}
In case you want to be efficient with the query:
You can use JPQL and hibernate
You can then write a query like:
String query = "select te.id from TestEntity te";
// Create the TypedQuery using EntityManager and then get ResultSet back
List<Long> ids = query.getResultList();
In case of using Spring-Data-Jpa, you can define the repository and define the method and pass the query with #Query annotation. Spring Data JPA
How do I map return value from Stored Procedure to my entity class in Hibernate. If selected column is been queried in SP.
try like
Query query = session.getNamedQuery("callStockStoreProcedure")
.setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i<result.size(); i++){
Stock stock = (Stock)result.get(i);
System.out.println(stock.getStockCode());
}
see this article
How to call stored procedure in Hibernate
You have the EntityManager.find(Class entityClass, Object primaryKey) method to find a specific row with a primary key.
But how do I find a value in a column that just have unique values and is not a primary key?
You can use appropriate JPQL with TypedQuery.
try {
TypedQuery<Bean> tq = em.createQuery("from Bean WHERE column=?", Bean.class);
Bean result = tq.setParameter(1, "uniqueKey").getSingleResult();
} catch(NoResultException noresult) {
// if there is no result
} catch(NonUniqueResultException notUnique) {
// if more than one result
}
For example, like this:
List<T> results = em.createQuery("SELECT t FROM TABLE t", T.class)
.getResultList();
With parameters:
List<T> results = em.createQuery("SELECT t FROM TABLE t where t.value = :value1")
.setParameter("value1", "some value").getResultList();
For single result replace getResultList() with getSingleResult():
T entity = em.createQuery("SELECT t FROM TABLE t where t.uniqueKey = :value1")
.setParameter("value1", "KEY1").getSingleResult();
One other way is to use Criteria API.
You can use a Query, either JPQL, Criteria, or SQL.
Not sure if your concern is in obtaining cache hits similar to find(). In EclipseLink 2.4 cache indexes were added to allow you to index non-primary key fields and obtain cache hits from JPQL or Criteria.
See,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching/Indexes
Prior to 2.4 you could use in-memory queries to query the cache on non-id fields.
TL;DR
With in DSL level - JPA no practice mentioned in previous answers
How do I find a value in a column that just have unique values and is not a primary key?
There isn't specification for query with custom field with in root interface of javax.persistence.EntityManager, you need to have criteria base query.
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<R> criteriaQuery = criteriaBuilder.createQuery(EntityType.class)
Root<R> root = criteriaQuery.from(type);
criteriaBuilder.and(criteriaBuilder.equal(root.get(your_field), value));
You can also group your predicates together and pass them all together.
andPredicates.add(criteriaBuilder.and(root.get(field).in(child)));
criteriaBuilder.and(andPredicates.toArray(new Predicate[]{});
And calling result(rather single entity or a list of entities) with
entityManager.createQuery(suitable_criteria_query).getSingleResult();
entityManager.createQuery(suitable_criteria_query).getResultList();
I got a Set<UserDTO> collection in a not Hibernate object, and I got a User domain entity in Hibernate.
UserDTO contains less information about user (only id and name)
How can I select full Hibernate User Set/List from the DTO object?
Like this?
Set<UserDTO> setDTO = .....
String hql = "FROM User WHERE id IN (:userDTO )";
Query query = entityManager.createQuery(hql);
query.setParameter("userDTO", setDTO);
return query.getResultList();
Thanks
Almost. But you'd have to extract the IDs in a separate collection first:
Set<Long> ids = new HashSet<Long>(setDTO.size());
for (UserDTO dto : setDTO) {
ids.add(dto.getId());
}
Then proceed with the query, and pass the ids set as param.
Don't forget that you need to use Query#setParameterList() instead of Query#setParameter.
So let's say I have an ArrayList full of Products that need to be committed to the database via Hibernate. There are already a large number of Products in the database. Each product has an ID. Note this is NOT the PK that is autogenerated by Hibernate.
My questions is: what is the best way to detect conflicts with this ID? I am looking for a relatively efficient method of obtaining, from the the database, a List of Products that share an ID with any of the Products in my ArrayList. This is all in a single table called Products and the ID attribute is in column ProductID.
The way I've done it is grabbing a list of all Products in the database, and compared each one with each entry in my ArrayList - but that is seriously inefficient and I don't think it would work well with a larger database. How should it be done? Thanks. I say "relatively" efficient because efficiency is not the primary concern, but it shouldn't take noticeably long to test against a table of ~1000-5000 rows. Help?
EDIT* I'm very new to hibernate and below is the best I've come up with. How does this look?
for(long id : idList){ //idList just holds the IDs of each Product in my ArrayList
Query query = session.createQuery("select product from Product product where product.id = :id");
query.setLong("id", id);
for(int i = 0; i < query.list().size(); i++){
listOfConflictingProducts.add((Product) query.list().get(i));
}
}
I would call query.list() only once: otherwise the query could be rerun each time:
for(long id : idList){ //idList just holds the IDs of each Product in my ArrayList
Query query = session.createQuery("select product from Product product where product.id = :id");
query.setLong("id", id);
List result = query.list();
for(int i = 0; i < result.size(); i++){
listOfConflictingProducts.add((Product) result.get(i));
}
}
Or, more simply:
for(long id : idList){ //idList just holds the IDs of each Product in my ArrayList
Query query = session.createQuery("select product from Product product where product.id = :id");
query.setLong("id", id);
for(Object obj: query.list()){
listOfConflictingProducts.add((Product)obj);
}
}