How do I access multiple fields in a JPA query? - java

I have a JPA query of the form:
SELECT category, count(*) AS c FROM ...
I know that if the query just returns a single column I can do something like:
List<Article> articles = query.getResultList();
However, how do I access the results when there are 2 or more columns as in the example above?

check out section 14.6 here: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql-select
it will return a List of Object[] if you select more than one column, but dont get the actual entity.

Related

JPA Update Multiple Records in Table for a ID

I have a requirement for a Input record with id1 from source, in target table I need to update value v1 in column c1 and in target for id1 there are multiple records. Using JPA I need to update all those records with value v1. Using JPA what is the best way to do this?
I used below
findallbyid() then saveall() - it failed saying there are mutliple records in target but expected was one.
Based on the details provided findallbyid() then saveall()
here the method findallbyid() is actually expecting to find only one record in the table, where as there are multiple rows.
changing the to signature of the method should work as expected without expection. As it expect capitalised words in method signature
https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html
List<T> findAllById(Long id);
but recommend not to read all rows and then save again just to update a column or two, you could use something like below to achieve the same
#Modifying
#Transactional
#Query(value = "UPDATE table t SET t.column = :status WHERE t.id = :id")
int update(#Param("status") String status, #Param("id") Long id);

Insert values in many to many relationship tables with JOOQ

I have three tables in my database, SUBSCRIPTION, USER_ID, and an association table called SUBSCRIPTION_USER_ID.
My strategy is to use JOOQ batch with three queries, the first one to insert on row into SUBSCRIPTION, the second query to insert multiple rows into USER_ID, and finally, I need to insert the association IDs into SUBSCRIPTION_USER_ID, so I did the following:
InsertValuesStep2 insertUserIds = insertInto(
USER_ID, USER_ID.USER_ID_TYPE, USER_ID.USER_ID_VALUE);
for (String userId : subscriptionDTO.getUserId())
insertUserIds = insertUserIds.values(getValue(0, userId), getValue(1, userId));
InsertReturningStep insertReturningUserIds = insertUserIds.onConflictDoNothing();
InsertResultStep insertReturningSubscription = insertInto(SUBSCRIPTION)
.set(SUBSCRIPTION.CHANNEL_ID, subscriptionDTO.getChannel())
.set(SUBSCRIPTION.SENDER_ID, subscriptionDTO.getSenderId())
.set(SUBSCRIPTION.CATEGORY_ID, subscriptionDTO.getCategory())
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
.onConflictDoNothing()
.returningResult(SUBSCRIPTION.ID);
Unfortunately, to insert values into the association table, I tried many ways but nothing works for me, finally, I tried to insert values in SUBSCRIPTION_USER_IDusing with select but It doesn't work:
InsertValuesStep insertValuesSubscriptionUserIds = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID)
.from(SUBSCRIPTION)
.innerJoin(USER_ID)
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))));
Am I missing something above? Is there a better way using JOOQ to insert many-to-many relationship values or to use queries results as parameters for other queries?
I'm assuming you posted your entire code. In case of which:
You don't call execute on your USER_ID insertion
Simply add
insertUserIds.onConflictDoNothing().execute();
Or alternatively, fetch the generated IDs using a call to returning().fetch()
Inner join
This might just be a stylistic question, but what you seem to be doing is a cross join. Your INNER JOIN filters aren't really join predicates. I'd put them in the WHERE clause. Clarity may help avoid further problems in such a query.
Specifically, that first "join predicate" is very confusing, containing a CONCAT call, which isn't something one would see in an INNER JOIN every day, and only touches one table, not both:
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
Wrong predicate
That last predicate seems wrong. You're inserting:
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
But you're querying
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getContactId()))));
That should probably be subscriptionDTO.getToken() again
As mentioned above, I have inserted values for SUBSCRIPTION and USER_ID tables. And get for the association table I need to get the IDs of the already inserted values from the above two tables, so to solve the issue I've used this query to insert in SUBSCRIPTION_USER_ID:
InsertReturningStep insertReturningSubscriptionUserId = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID).from(SUBSCRIPTION
.where(concat(USER_ID.USER_ID_TYPE, val(CATEGORY_USER_ID_DELIMITER), USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId()))
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))).onConflictDoNothing();
Finally, I have executed all the queries using batch:
using(configuration).batch(insertReturningSubscription,
insertReturningUserIds,
insertReturningSubscriptionUserId).execute()

Hibernate Criteria API - update many rows with one database query

I'm fetching from database bunch of persons like this:
public List<Object[]> getLimitedBunchOfPersons(Integer limit) {
Criteria criteria = getSession().createCriteria(Person.class, "person")
.setProjection(
Projections.projectionList()
.add(Projections.property("person.personId"), "personId")
)
.createAlias("person.status","status")
.add(Restrictions.eq("status.statusId", 1L))
.addOrder(Order.asc("person.createdOn"));
return criteria.setMaxResults(limit).list();
}
As I needed to speed things up, I only fetched ID's of my entity. Important thing to note is that I'm manipulating with large number of rows and for one query had to use maxResults limitation.
Now my problem is, how to easily update with Hibernate Criteria API in one database query all fetched rows from previously mentioned query?
Plain SQL query would go something like this:
UPDATE PERSON
SET STATUS = 2, CREATED_ON = CURRENT_TIMESTAMP
WHERE STATUS = 1;
It's important to note that update method have to use same order and limit as getLimitedBunchOfPersons() method.
For Single Object it will work as follows after your code
Person per= (Person) criteria.uniqueResult();
per.setCreatedOn("crtBy");
currentSession.merge(per);
Now if comes in list you can iterate list by passing mentioned code in your List iteration

Force ebean to not include an ID in a generated query

I'm building a select that has to get me all distinct values from a table.
The sql I would normally write would look like this: "SELECT DISTINCT ARTIST FROM MUSICLIB"
However, ebean is generating the following: "SELECT DISTINCT ID, ARTIST FROM MUSICLIB"
The finder is as such:
find.select("artist").setDistinct(true).findList();
I've found that ebean is generating this ID on every single query, no matter what options I set.
How do I accomplish what I'm looking for?
You can't do that, Ebean for objects mapping requires ID field, and if you won't include it you'll get some mysterious exceptions.
Instead you can query DB without mapping and then write your SQL statement yourself:
SqlQuery sqlQuery = Ebean.createSqlQuery("SELECT DISTINCT artist FROM musiclib");
List<SqlRow> rows = sqlQuery.findList();
for (SqlRow row : rows) {
debug("I got one: " + row.getString("artist"));
}
Of course if artist is a relation, you need to perform additional query using list of found IDs with in(...) expression.

Android ormlite query sort by another table

I want to query my data from A and order-by a field from B, The field in B could be null. Any suggestions? Thanks.
As of version 4.22, ORMLite now supports simple JOIN query syntax. Here is the documentation for it:
http://ormlite.com/docs/join-queries
So your query might be something like:
QueryBuilder<B, Integer> bQb = bDao.queryBuilder();
bQb.orderBy("someBField", true);
QueryBuilder<A, Integer> aQb = aDao.queryBuilder();
List<A> results = aQb.join(bQb).query();
You can also certainly use the dao.queryRaw() methods to construct you own query. Here a good example how you would formulate the query:
SQL order by a column from another table

Categories

Resources