Get data from 2 different tables using JPA jax-rs REST service - java

If I have one table named A_client, and another one named B_client. A_client has ID's and different status values, while B_client is holding personal data, such as name and adress.
How do I do this if I followed this guide?
Examples below to show you where I am
I have a A_Client.java that looks like this:
#Entity
#Table(name = "A_client")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "AClient.findAll", query = "SELECT e FROM AClient e"),
#NamedQuery(name = "AClient.findById", query = "SELECT e FROM AClient e WHERE e.Id = :Id"})
And I have a A_ClientFacadeREST that looks like this:
#Stateless
#Path("test")
public class AClientFacadeREST extends AbstractFacade<AClient> {
#PersistenceContext(unitName = "com.123_MavenProjectTest_war_1.0-SNAPSHOTPU")
private EntityManager em;
public AClientFacadeREST() {
super(AClient.class);
}
#GET
#Path("id")
#Produces({"application/xml", "application/json"})
public List<AClient> findById() {
List<AClient> results = em.createNamedQuery("AClient.findById", AClient.class)
.setParameter("Id", 1)
.getResultList();
return results;
}
etc etc
How do I manage to get data from B_Client aswell as A_Client using REST?

Just set OneToOne relations between tables in your AClient entity

Related

No query defined for that name [getUserByCity], Spring boot JPA NamedQuery from jpa-named-queries.properties

There are many existing questions for this issue but my case is little different because I am trying to use named query in EntityManager.
I am trying to use named query(Defined in jpa-named-queries.properties not using #NamedQuery) in EntityManager but I am always getting No query defined for "name".
I have a class User
#Entity
#Table(name = "USER") // Note have column configuration also, not bring here to clear the code
class User{
// My Properties
}
I have its repository which is extended from JpaRepository as well as from CustomUserRepository.
Here is my customer user repository.
interface CustomUserRepository{
List<User> executeQuery(String named, List<Object> params);
}
// its implementation class is something like this.
class CustomUserRepositoryImpl implements CustomUserRepository{
#PersistenceContext
private EntityManager manager;
List<User> executeQuery(String named, List<Object> params){
javax.persistence.Query namedquery = getEntityManager().createNamedQuery(query);
int[] idx = { 1 };
parameters.stream()
.filter(p-> p!=null)
.forEach((m)->
namedquery.setParameter(idx[0]++, m));
return namedquery.getResultList();
}
}
I am using this executeQuery method from user repository.
Everything works fine if I declare named query above User class as follows.
#Entity
#Table(name = "USER") // Note have column configuration also, not bring here to clear the code
#NamedQuery(name = "getUserByCity",
query = "from User u where u.city= ?1")
class User{
// My Properties
}
But not working If I am adding named query in src/main/resources/META-INF/jpa-named-queries.properties with this I am getting no named query found for this key. following is my jpa-named-queries.properties file contents
getUserByCity=from User u where u.city= ?1
# also tried User.getUserByCity=from User u where u.city= ?1

Retrieving #NamedQuery from interface of JPA Entity

I have a JPA 2.1 project, database has 2 tables. I have created an interface "UsedClasses.java" and have both Entities implement the interface., i.e.
#Entity
#Table(name = "runRanges")
#NamedQuery(name = "RunRange.findAll", query = "SELECT r FROM RunRange r")
public class RunRange extends AbstractTimestampEntity implements UsedClasses, Serializable ....
and
#Entity
#Table(name = "users")
#NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")
public class User extends AbstractTimestampEntity implements UsedClasses, Serializable ...
I am curious to know if I can use the interface to grab the NamedQuery for either of the Entities.
What I am trying to accomplish if getting the results list according to the class.
public List<UsedClasses> getAllItems() {
open();
Query query = EntityManagerHandler.INSTANCE.getEntityManager().createQuery(UsedClasses.class.getResource(NamedQueries));
List<UsedClasses> aList = query.getResultList();
return aList;
}
You can do it but you should use reflection to retrieve the NamedQuery annotation and you would need to have the UsedClasses instance and not the interface like in your example :
Query query = EntityManagerHandler.INSTANCE.getEntityManager().createQuery(UsedClasses.class.getResource(NamedQueries));
Besides, if you add multiple annotations, it will not work any longer.
I think that a more simple and clean solution would be to add a method in your interface to get the namedQuery String name.
For example
public interface UsedClasses(){
String getNamedQueryForGetAll();
}
And you could implement it in this way :
#Entity
#Table(name = "users")
#NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")
public class User implements UsedClasses(){
public String getNamedQueryForGetAll(){
return "User.findAll";
}
}
Then you can use it in this way :
Query query = EntityManagerHandler.INSTANCE.getEntityManager().createQuery(usedClassInstance.getNamedQueryForGetAll());
Now, I find that it creates a little of duplication and it is not straight readable.
NamedQuery brings a extremely tiny performance improvement.
I am not sure that the complexity/indirection level introduced in the code to gain so few in terms of execution time makes you winning.

Why I obtain this HibernateException (Errors in named queries) related to my JPQL query?

I am absolutly new in Hibernate and I have the following problem defining a JPQL query into an application.
So I have the following situation:
1) I have this model KMCountryArea class that is annoted to map it to a DB table and a query is definied
#NamedQueries({
#NamedQuery(name = "kmCountryListByName", query = "SELECT country FROM KMCountryArea country WHERE country.nomeFolder = :nomeFolder order by country.idCountry")
})
#Entity
#Table(name = "KM_COUNTRY_AREA")
public class KMCountryArea implements Serializable {
#Id
#GeneratedValue
private Long idCountryArea;
#Column(name = "nomeFolder")
private String nomeFolder;
//#Column(name = "country")
//#OneToOne(mappedBy = "country", cascade = CascadeType.ALL)
#OneToOne
private KMCountry country;
public Long getIdCountryArea() {
return idCountryArea;
}
public void setIdCountryArea(Long idCountryArea) {
this.idCountryArea = idCountryArea;
}
public String getNomeFolder() {
return nomeFolder;
}
public void setNomeFolder(String nomeFolder) {
this.nomeFolder = nomeFolder;
}
public KMCountry getCountry() {
return country;
}
public void setCountry(KMCountry country) {
this.country = country;
}
}
As you can see in the previous code snippet I defined a JPQL query named kmCountryListByName, this one:
#NamedQueries({
#NamedQuery(name = "kmCountryListByName", query = "SELECT country FROM KMCountryArea country WHERE country.nomeFolder = :nomeFolder order by country.idCountry")
})
2) Then I have a DAO defining an interface named KMCountryAreaService, this one:
public interface KMCountryAreaService {
#Transactional
public List<KMCountry> getCountryListByName(Long idCountry);
}
that is implemented by the KMCountryAreaServiceImpl concrete class:
#Repository("kmCountryAreaService")
public class KMCountryAreaServiceImpl extends AbstractService implements KMCountryAreaService {
public List<KMCountry> getCountryListByName(Long idCountry){
List<KMCountry> list = getHibernateTemplate().findByNamedQuery("kmCountryListByName");
return list;
}
}
So, as you can see, the getCountryListByName() method obtain the kmCountryListByName that I defined into the model class (KMCountryArea).
The problem is that when I try to startup my application (it is a LifeRay portal but I think that it is not important) I obtain the following error message in the stacktrace:
<Stack trace for message 149004
weblogic.application.ModuleException: :org.hibernate.HibernateException:Errors in named queries: kmCountryListByName
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:365)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1300)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:860)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:779)
Truncated. see log file for complete stacktrace
>
It seems that I have some error on my JPQL query (the one named kmCountryListByName defined into the model class) or maybe into the KMCountryAreaServiceImpl service implementation.
Why? What am I missing? How can I solve this issue?
Try something like this:
#NamedQueries({
#NamedQuery(name = "kmCountryListByName", query = "SELECT c FROM KMCountryArea c WHERE c.nomeFolder = :nomeFolder order by c.idCountryArea")
})
You have a country property, at the same time you are trying to make alias with the country name.
Or are you trying to join them?
If you try to join them and order by a specific property in the Country object you can try something like this
#NamedQueries({
#NamedQuery(name = "kmCountryListByName", query = "SELECT c FROM KMCountryArea c JOIN c.country cc WHERE c.nomeFolder = :nomeFolder order by cc.idCountry")
In the example above you can see the join between the two objects and order by clause based on the Country object property

Play JPA Query Example

How to get JPA work in Play MVC. I tried a lot of variants. But all unsuccesfull.
public class Application extends Controller {
public static void book() {
EntityManager em = JPA.em();
List<Book> bookList = em.createNativeQuery("select * from book").getResultList();
render( bookList );
}
public static void index() {
render( );
}
}
I got error like this:
A JPA error occurred (The JPA context is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the #javax.persistence.Entity annotation are found in the application.):
Second variant doesnt' work:
#NamedQuery(name = "findFoo", query = "select f from Foo f where f.state in :stateInList")
final Query query = this.entityManager.createNamedQuery("findFoo");
How to get worked with NamedQuery ?? Where to place NamedQuery ??
your named query is correct and you can write it above the entity
#Entity
#Table(name = "Foo")
#NamedQuery(
{
#NamedQuery(name = "findFoo", query = "select f from Foo f where f.state in :stateInList")
)}
public class Foo
{
....
}

How to map an abstract class or interface in Hibernate HQL?

Imagine that I have a Debtor class. With Hibernate, I will define the class like that:
#Entity
#Table(name = "T_DEBTOR")
public class Debtor {
#Id
#Column(name = "ID_DEBTOR")
private String idDebtor;
...
My DAO will then looks like:
public class DebtorDaoImpl implements DebtorDao {
#PersistenceContext
private EntityManager em;
#SuppressWarnings("unchecked")
public List<Debtor> findAllDebtors() {
Query q = em.createQuery("select d from Debtor d");
return (List<Debtor>) q.getResultList();
}
This works well. However, I am in a configuration where I need to access differents schemas (as pointed here). Of course, in each schema the table that hosts the debtor list has not the same name. In addition to that, they may not have the exact same structure. That why I have x differents Debtor class (where x is the number of schemas I manipulate).
In the case where I have two differents schemas, I will have two different Debtor class: DebtorOne and DebtorTwo.
As I want to ease my developments, I created an Interface (or an Abstract class, it does not change my problem here) that is implemented by both DebtorOne and DebtorTwo:
public interface Debtor {
String getIdDebtor();
}
and:
#Entity
#Table(name = "T_DEBTOR_ONE")
public class DebtorOne implements Debtor {
#Id
#Column(name = "ID_DEBTOR")
private String idDebtor;
...
If I let my DAO as it is, I get the following error from Hibernate:
Caused by: org.hibernate.hql.ast.QuerySyntaxException: Debtor is not mapped [select d from Debtor d]
If I change my DAO to have this:
public List<Debtor> findAllDebtors() {
Query q = em.createQuery("select d from DebtorOne d");
return (List<Debtor>) q.getResultList();
}
then it works, but it is specific to DebtorOne schema...
One solution I see is to define a named query on the DebtorOne and DebtorTwo classes and call this named query from my DAO.
In others words:
#Entity
#Table(name = "T_DEBTOR_ONE")
#NamedNativeQueries( { #NamedNativeQuery(name = "findAllDebtors", query = "select d from DebtorOne d") })
public class DebtorOne implements Debtor {
and in the DAO:
#SuppressWarnings("unchecked")
public List<Debtor> findAllDebtors() {
Query q = em.createNamedQuery("findAllDebtors");
return (List<Debtor>) q.getResultList();
}
I didn't try it yet, but I think it will work...
EDIT I just tried, this will work... except that the NamedQuery must be named differently for DebtorOne and DebtorTwo...
However, I am wondering if there is a way to solve my problem without using the latter solution?
Edit regarding the first answer, which suggests to use the #MappedSuperclass. This annotation seems to be the perfect solution for me, but I think I forgot something, as I still get the same error.
The main Debtor:
#MappedSuperclass
public class Debtor {
#Id
#Column(name = "IDDEBTOR")
protected String idDebtor; // With getter and setter
}
one of the extended Debtor class:
#Entity
#Table(name = "DEBTOR_ONE")
public class DebtorOne extends Debtor {
...
and in my DAO:
public List<Debtor> findAllDebtors() {
return (List<Debtor>) em.createQuery("select d from Debtor d").getResultList();
}
is still returning me the error Caused by: org.hibernate.hql.ast.QuerySyntaxException: Debtor is not mapped [select d from Debtor d]
What did I miss this time?
I think this is not possible with an interface, but only with a common abstract base class, that will be annotated with #MappedSuperclass (see Hibernate documentation for further details)
I think for this to work you'd either have to actually map the Debtor table to a table or use the table per class strategy (union-subclass). #MappedSuperClass only seems to implement a very rudimentary mechanism to copy properties and wouldn't work because you can't query for instances of the superclass.
I take it from the link that you already have something in place to avoid mapping DebtorTwo in the hibernate session for the schema of DebtorOne (otherwise querying Debtor would pull in all records, including ones from the DebtorTwo table that wouldn't exist). In that case, follow the example from the documentation to map the subclass for either case.

Categories