Use custom query for built-in entities in liferay 6.1? - liferay-6

I have read many posts about creating service layer in liferay. I was able to build a service layer and custom query sample project in eclipse. However, all of the examples I got so far is about adding new entities and performing CRUD actions on those new entities.
I want to ask is it possible to use custom query with built-in entities?. For example, I want to use custom query with JounalArticle, AssetEntry, and so on.
If that possible, how can I do that. Please give me some hints or examples.
(I have tried dynamic queries with sub queries but they do not meet my requirements)

If someone is interested:
In the XXXLocalServiceImpl you can add:
public List<JournalArticle> getArticles(String username) {
Session session = xxxPersistence.openSession();
try {
String sql = "SELECT * FROM journalarticle ja WHERE ja.userName like '%"+username+"%'";
SQLQuery query = session.createSQLQuery(sql);
return query.list();
}finally {
session.close();
}
}
rerun your service builder and you can use form XXXLocalServiceUtil.getArticles("Test Test")
Using service builder: create database portlets

Related

EF CORE loads all data before any query takes place

I have a console app to test EF Core with SQL Server Express edition. I have the following code in Program.cs
using EFCoreTutorials;
using EFCoreTutorials.Entities;
using Microsoft.EntityFrameworkCore;
using (var context = new SalesManagementContext())
{
var employees = context.Employees.ToList();
}
I wonder why context.Employees brings all data from my employees table without even asking for it with a query. If I have many tables in my database and my context class with a lot of data , are all these available from the context var at the beginning of program without even specifying which one of these I actuall want to use?
Thank you

Spring JPA Specification API with custom Query and custom response Object. Is this possible?

I have researched this for a few days but can't seem to find the right information.
Here is what I need, I have a Database, with multiple tables, I need to join a few tables together to make a sort of "search" API. I have to implement the ability to dynamically search fields (from various tables in the query), sortable, with pagination.
I have found that I cannot combine the #Query annotation with Specification API, and I looked into using the specification API to do the joins I needed but, the problem is the root must be one table/repository.
For example:
If I have a users table that has to join on addresses, phone_numbers, and preferences
the base repository will be UserResposiory and it will return the User entity model, but I need it to return a custom DTO
AccountUserDTO which contains fields from the User, Address, PhoneNumber, and Preference entities.
Would anyone know if this is possible at all??
I am at wits end here and I really want to build this the correct way.
Cheers!
You may do this way:
Build hql query as an string, depend on how the filter condition is requested, you can build the corresponding query, eg:
if (hasParam(searchName)) {
queryString = queryString + " myEntity.name = :queryName"
}
Query query = session.createQuery(queryString);
and the parameter providing
if (hasParam(searchName)) {
query.setParameter("queryName", searchName);
}
...
and execute it.
To create a customized object, the easiest way is treating the object as an array of field:
Query query = session.createQuery("select m.f1, m.f2, m.f3 from myTable m");
List managers = query.list();
Object[] manager = (Object[]) managers.get(0); //first row
System.out.println(manager[0]) //f1
System.out.println(manager[1]) //f2
System.out.println(manager[2]) //f3
There is also some other solution to select, such as
String query = "select new mypackage.myclass(m.f1, m.f2, m.f3) from myTable m";
-> And when execute the above query, it will return a list of object.
Or to be simpler, make your own view in db and map it to one entity.

How to execute scalar query on an IMobileServiceSyncTable?

I'm moving my app over from Sqlite-Net to Azure Mobile Services and I'm adding offline sync capabilities.
I'm unsure how to execute arbitrary queries. This is what I have for Sqlite-Net:
var newestDate = await this.connection.ExecuteScalarAsync<DateTime> ("SELECT MAX(TimeStamp) FROM SupplyData");
How can I run this query against my IMobileServiceSyncTable instance?
There is a CreateQuery() method but it does not take any parameters.
Is there any reason you can't use LINQ?
// This query filters out completed TodoItems and items without a timestamp.
List<TodoItem> items = await todoTable
.Where(todoItem => todoItem.Complete == false)
.ToListAsync();
Reference: https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-dotnet-how-to-use-client-library/#filtering
The alternate to this is to call a custom API. In ASP.NET backends, this is just a WebAPI that uses the underlying Entity Framework stuff. See https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-dotnet-backend-how-to-use-server-sdk/#how-to-define-a-custom-api-controller For Node.js backends (or Easy Tables / Easy API), see the following sample code: https://github.com/Azure/azure-mobile-apps-node/tree/master/samples/custom-api-sql-stmt

Spring LDAP JPA - Limit number of result

I'm using spring-ldap 2.0.4 and spring-data-jpa 1.9.0.
I built a JPA repository like this :
public interface PersonRepo extends LdapRepository<Person> {
Person findByUid (String uid);
#Query("(&(attribute=*{0}*)(attribute2=X)(attribute3=Y))")
List<Person> findByAttributeContains(String attribute);
}
So far everything is fine. I could write methods that fill my needs thanks to query methods.
For some queries i had to use #Query annotation because they were many and operator.
But i would like to limit the number of result to return from my second query method.
I know there is there is the Top and First keywords to define query methods in spring JPA. But I didn't manage to get it work. Plus I want to use multiple and operator in the method.
Thanks
I managed to limit the number of result using XML LDAP configuration.
<ldap:ldap-template context-source-ref="contextSource" count-limit="100"/>

How to get the JPA generated SQL query?

I use JPA specification and Hibernate as my vendor. I need somehow to take the generated SQL Query which is sent to the the DB (printed to the sysout) and save it as a simple string.
Is there a way to do this?
EDIT
Let me make it a beat clearer: I don't need hibernate log. I need to be able to execute the same query on a different DB. Therefore, I need to get the SQL query as is, and hold it in a normal String variable.
Edit 2
Is there a util which I can provide it a bean and it will automatically generate an Insert query? can I somehow use Hibernate beans here? I know it's a beat complex.
Thanks,
Idob
Create a bean like this.
#Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(true);
jpaVendorAdapter.setShowSql(true);
return jpaVendorAdapter;
}
If you're using Spring Boot add it somewhere to your #Configuration.
The logs created from this are executable in MySQL workbench.
You stated that you are using JPA and Hibernate. There's no other way except if the database you support are supported by JPA. In that case there is an AbstractJpaVendorAdapter that you can implement.
The simple answer to your question is No. What you want to do is something that many developers would also like to do however it was not part of the JPA specification and thus the ability to get the generated SQL will depend upon what the vendor decided to do. Using Hibernate the only way to obtain the SQL is via the log.
You have to enable the log4j logging and add an appender for Hibernate to show the queries.
This has already been described here: How to print a query string with parameter values when using Hibernate
If I understand you correctly, you want to get the insert query which Hibernate is executed on one database, and via code, run it on a different database via entityManager#executeUpdate or similar.
Hibernate does not expose the generated query as it is specific for the dialect of target database. So even if were to get the insert query, it could be pointless.
However in your case, you can create two database connections (via two DataSource or EntityManagerFactory whatever in your case) and call dao.persist(entity) two times for both databases, and let Hibernate handle the query construction part.
Edit: By query I mean native query here, HQL query would be same for both databases.
Hope it helps.
I don't know what you mean by a generated query but if you use Hibernate and you have javax.persistence.Query query you can get HQL string very easy (for EclipseLink it is similar). And if you have HQL you can translete it to SQL with QueryTranslator.
// Get HQL
String hqlQueryString = query.unwrap(org.hibernate.query.Query.class).getQueryString();
// Translate HQL to SQL
ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
SessionImplementor hibernateSession = em.unwrap(SessionImplementor.class);
QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", hqlQueryString, Collections.emptyMap(), hibernateSession.getFactory(), null);
queryTranslator.compile(Collections.emptyMap(), false);
String sqlQueryString = queryTranslator.getSQLString();
Try to add properties in instance of LocalContainerEntityManagerFactoryBean ,Its working for me :-
#EnableJpaRepositories(basePackages = "org.common.persistence.dao")
public class PersistenceJPAConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "org.common.persistence.model" });
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
final Properties additionalProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("showSql", "true");
hibernateProperties.setProperty("hibernate.show_sql", "true");
hibernateProperties.setProperty("hibernate.format_sql", "true");
hibernateProperties.setProperty("hibernate.query.substitutions", "false");
return hibernateProperties;
}
}