Association of 4 tables in hibernate - java

I have 4 tables involved in this query.
Campaign - many to one business
Business - one to many client
Client - one to one contact
Contact
In contact there is the field contact_name which is unique. I need to retrieve all campaigns related to contact(via client and business) which campaign field type equals 2.
What is the best way to do it with hibernate?
In SQL is will look like this:
select *
from campaign,contact, business, client
where campaign.type=2
and client.contact_id = contact.contact_id
and contact.name = 'Josh'
and client.business_id = business.business_id
and campaign.campaign_id = business.business_id

I think that the following should work.
from Compaign where Compaign.type=2 and compaign.business.client.contact.contact_name=:name

You can execute native SQL Queries too using createSQLQuery() method of Session.
You can also use Scalar Property to avoid the overhead of using ResultSetMetadata.
You can find more information on this from here

Related

How do you structure or do a query in Hyperledger-fabric(Java SDK) with CoachDB?

As the tittle says I want to create some transactions to make queries. In my case I have Wallet and Customer classes and each of them has a type attribute for knowing what type they are. I want, for example to make a query to get all the wallets so I guess I would have to create a query like TYPE=WALLET. The code I use to query is the following.
String queryStr = "{\"selector\": {\"type\": \"wallet\"}}";
QueryResultsIterator<KeyValue> rows = stub.getQueryResult(queryStr);
The things that I don’t know who to structure the string for querying, of if there is a better way of doing this type of queries. Thanks for your help.

Select additional information with Hibernate Criteria

I have following code:
session
.createCriteria(MyObj.class)
.add(Restrictions.
sqlRestriction("1=1 CONNECT BY conn_by = PRIOR id START WITH id = ?",
id, Hibernate.LONG)).list();
This code works however I want to select also level information (used with connect_by in Oracle). How I can select also this value? I do not consider level information as part of the MyObj class.
Thanks in advance.
Hibernate criteria will return only information that is available in MyObj.class ...according to you if your class don't have level info then it will give you error

Hibernate query fails with "this_.id must appear in GROUP BY" when using projection.count or projection.rowcount

Edited to provide more detailed information.
I'm building a web service using Spring 2.5.6 and Hibernate 4. I'm dynamically building a criteria query based on input from a client. We are using Spring 2.5.6 because it is legacy code, previous attempts to upgrade to later versions of Spring by updating the versions in the Maven POM file fail, and our deadline is too tight to provide time to fully transition the project to a later version of Spring.
The web service is searching for observations made by sensors using filters sent to the service by a client over SOAP. The users of this web service have need to create filters that result in several thousand observations returned. The service is taking so long to return a response, the users' clients are timing out. What I am attempting to do to resolve this performance issue is first query the database for how many observations would be returned by the users' filters, then splitting the work off into several threads of execution using a cached thread pool. Each thread will query the database for a portion of the results. Then using a thread-safe queue provided by Java's java.util.concurrent package, I have each thread encode the responses into the proper JAXB objects and add these objects to the queue. Finally, the web service returns the entire response to the client.
I'm hoping this design will reduce response time (it obviously assumes the database will handle the multiple parallel queries just fine and that returning the results from the database in pieces along several connections is faster than one bulk return on a single connection). However, when attempting to get that initial count required before creating my threads, I get an error from the database.
I'm using Hibernate criteria queries and a Hibernate projection to get the count. The criteria is generated by the code below:
Criteria criteria = session.createCriteria(Observation.class);
if (!filter.isSetService())
{
throw new JpaCriteriaFactoryException("Service required for ObservationFilter.");
}
criteria.createAlias("sensor", "sensor").add(Restrictions.eq("sensor.service", filter.getService()));
criteria = criteria.setMaxResults(filter.getMax());
criteria = criteria.setFirstResult(filter.getStart());
criteria = criteria.addOrder(Order.desc("id"));
if (filter.isSetOffering())
{
// offerings will be implemented later
}
if (filter.isTemplate())
{
criteria = criteria.add(Restrictions.eq("template", true));
}
else
{
criteria = criteria.add(Restrictions.eq("template", false));
}
if (filter.isSetProcedures())
{
criteria = criteria.add(Restrictions.in("sensor.uniqueId", filter.getProcedures()));
}
if (filter.isSetPhenomenons())
{
criteria = criteria.createAlias("phenomenon", "phenom")
.add(Restrictions.in("phenom.id", filter.getPhenomenons()));
}
if (filter.isSetTemporalFilter())
{
criteria = criteria.add(createTemporalCriteria(filter.getTemporalFilter()));
}
if (filter.isSetGeospatialFilter())
{
criteria = criteria.createAlias("featureOfInterest", "foi")
.add(createGeospatialCriteria("foi.geometry",
filter.getGeospatialFilter(), geoFac));
}
if (filter.isSetScalarFilter())
{
try
{
criteria = criteria.createAlias(RESULTS_ALIAS, RESULTS_ALIAS)
.add(ScalarCriterionFactory.createScalarCriterion(filter.getScalarFilter(), RESULTS_ALIAS));
}
catch (ScalarCriterionFactoryException ex)
{
throw new JpaCriteriaFactoryException("Failed to build criterion for scalar filter!", ex);
}
}
return criteria;
Then, to get the count of the results, rather than the results themselves, criteria.setProjection(Projections.rowCount()) is added. However, this results in the following exception:
org.postgresql.util.PSQLException: ERROR: column "this_.id" must appear in the GROUP BY clause or be used in an aggregate function
In hibernate, I added the following settings:
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
and got the following output:
/* criteria query */ select
count(*) as y0_
from
Observation this_
inner join
Sensor sensor1_
on this_.sensor_id=sensor1_.id
where
sensor1_.service_id=?
and this_.template=?
and sensor1_.uniqueId in (
?
)
order by
this_.id desc limit ?
Using the exact same filter to generate a criteria, but not adding criteria.setProjection(Projections.rowCount()), I get the exact results I'm expecting. So I do not feel that the criteria is being created incorrectly. I cannot use criteria.list().size() because the whole point of this is to get the results back in parallel rather than in serial.
Can someone please help me to resolve this issue? If a better solution then my "threading" solution is available, I am also open to suggestions.
The problem is the statement:
criteria = criteria.addOrder(Order.desc("id"));
It should be removed, as the generated 'order by' clause is not required when setting the projection:
criteria.setProjection(Projections.rowCount());
Proceeding to add the proposed 'group by' clause isn't the way to go, as it'll result in a list, where each row will have an 'id' value and a row count value of 1 (for the columns).
In the end the statement:
criteria.uniqueResult();
Will throw an exception for multiple result values.
I've identified the solution to this.
What I really needed was a Hibernate equivalent of SELECT count(*) FROM (SELECT ... ) Per https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch16.html#queryhql-subqueries, this is not allowed in HQL. Also, based on https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch17.html#querycriteria-detachedqueries, it appears that legacy Hibernate Criteria does not support this function either, since the way of creating subqueries there is to use DetachedCriteria adding these via the Subqueries class. It does appear to be doable using formal JPA CriteriaBuilder per http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch12.html#querycriteria-from, however due to the architecture currently employed in my service, I am unable at this time to use this feature.

Order by another table with Liferay's DynamicQuery

I have a problem while I'm making a Dynamic Query in Liferay 6. I'm trying to make a query to order JournalArticles based on their view count. The view count is specified in another table (AssetEntry).
I'm stuck with this:
DynamicQuery query = DynamicQueryFactoryUtil.forClass(
JournalArticle.class, "articleParent", PortalClassLoaderUtil.getClassLoader());
//adding criterions
query.add(...);
DynamicQuery dq0 = DynamicQueryFactoryUtil.forClass(AssetEntry.class, "asset",
PortalClassLoaderUtil.getClassLoader())
.setProjection(ProjectionFactoryUtil.property("asset.classPK"))
.add(PropertyFactoryUtil.forName("asset.companyId")
.eqProperty("articleParent.companyId"))
.add(PropertyFactoryUtil.forName("asset.groupId")
.eqProperty("articleParent.groupId"));
query.add(PropertyFactoryUtil.forName("articleParent.resourcePrimKey").in(dq0))
.addOrder(OrderFactoryUtil.desc("asset.viewCount"));
With this I get an error message saying: could not resolve property: asset of: com.liferay.portlet.journal.model.impl.JournalArticleImpl.
If I remove the addOrder-call, this error disappears. How should I add the order statement so the main query is aware of asset.viewCount?
AssetEntryQuery assetEntryQuery = new AssetEntryQuery();
assetEntryQuery.setClassName(JournalArticle.class.getName());
assetEntryQuery.setXXX //adding criterions
assetEntryQuery.setOrderByCol1("viewCount");
List<AssetEntry> assetEntries = AssetEntryServiceUtil.getEntries(assetEntryQuery);
I am afraid that there is no direct way to do this with the DynamicQuery API.
I think you would need to use Service builder Finders i.e. Custom Query with Service builder.
You can't use dynamic query because there is no direct reference from JournalArticle entity to AssetEntry entity.
One possibility is to retrieve ordered ids of articles from the AssetEntry table (basically you dq0), then do another query and do the sorting programatically (you have the ids ordered).
Finally I think that this line
query.add(PropertyFactoryUtil.forName("articleParent.resourcePrimKey").in(dq0))
doesn't do what you think it does. resoucePrimKey is reference to resource table for permissions. You need to use id column.

How to store all user activites in a website..?

I have a web application build in Django + Python that interact with web services (written in JAVA).
Now all the database management part is done by web-services i.e. all CRUD operations to actual database is done by web-services.
Now i have to track all User Activities done on my website in some log table.
Like If User posted a new article, then a new row is created into Articles table by web-services and side by side, i need to add a new row into log table , something like "User : Raman has posted a new article (with ID, title etc)"
I have to do this for all Objects in my database like "Article", "Media", "Comments" etc
Note : I am using PostgreSQL
So what is the best way to achieve this..?? (Should I do it in PostgreSQL OR JAVA ..??..And How..??)
So, you have UI <-> Web Services <-> DB
Since the web services talk to the DB, and the web services contain the business logic (i.e. I guess you validate stuff there, create your queries and execute them), then the best place to 'log' activities is in the services themselves.
IMO, logging PostgreSQL transactions is a different thing. It's not the same as logging 'user activities' anymore.
EDIT: This still means you create DB schema for 'logs' and write them to DB.
Second EDIT: Catching log worthy events in the UI and then logging them from there might not be the best idea either. You will have to rewrite logging if you ever decide to replace the UI, or for example, write an alternate UI for, say mobile devices, or something else.
For an audit table within the DB itself, have a look at the PL/pgSQL Trigger Audit Example
This logs every INSERT, UPDATE, DELETE into another table.
In your log table you can have various columns, including:
user_id (the user that did the action)
activity_type (the type of activity, such as view or commented_on)
object_id (the actual object that it concerns, such as the Article or Media)
object_type (the type of object; this can be used later, in combination with object_id to lookup the object in the database)
This way, you can keep track of all actions the users do. You'd need to update this table whenever something happens that you wish to track.
Whenever we had to do this, we overrode signals for every model and possible action.
https://docs.djangoproject.com/en/dev/topics/signals/
You can have the signal do whatever you want, from injecting some HTML into the page, to making an entry in the database. They're an excellent tool to learn to use.
I used django-audit-log and I am very satisfied.
Django-audit-log can track multiple models each in it's own additional table. All of these tables are pretty unified, so it should be fairly straightforward to create a SQL view that shows data for all models.
Here is what I've done to track a single model ("Pauza"):
class Pauza(models.Model):
started = models.TimeField(null=True, blank=False)
ended = models.TimeField(null=True, blank=True)
#... more fields ...
audit_log = AuditLog()
If you want changes to show in Django Admin, you can create an unmanaged model (but this is by no means required):
class PauzaAction(models.Model):
started = models.TimeField(null=True, blank=True)
ended = models.TimeField(null=True, blank=True)
#... more fields ...
# fields added by Audit Trail:
action_id = models.PositiveIntegerField(primary_key=True, default=1, blank=True)
action_user = models.ForeignKey(User, null=True, blank=True)
action_date = models.DateTimeField(null=True, blank=True)
action_type = models.CharField(max_length=31, choices=(('I', 'create'), ('U', 'update'), ('D', 'delete'),), null=True, blank=True)
pauza = models.ForeignKey(Pauza, db_column='id', on_delete=models.DO_NOTHING, default=0, null=True, blank=True)
class Meta:
db_table = 'testapp_pauzaauditlogentry'
managed = False
app_label = 'testapp'
Table testapp_pauzaauditlogentry is automatically created by django-audit-log, this merely creates a model for displaying data from it.
It may be a good idea to throw in some rude tamper protection:
class PauzaAction(models.Model):
# ... all like above, plus:
def save(self, *args, **kwargs):
raise Exception('Permission Denied')
def delete(self, *args, **kwargs):
raise Exception('Permission Denied')
As I said, I imagine you could create a SQL view with the four action_ fields and an additional 'action_model' field that could contain varchar references to model itself (maybe just the original table name).

Categories

Resources