I've been trying to get all rows from table in EclipseLink.
I created my entities from db with the JPA tools. This is the result:
#Entity
#Table(name="employee", schema="hr")
#NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
public Employee() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
I found many pages where people create Query object to get all the records but they define again the "select" query like this.
Query q = em.createQuery("select e from Employee e");
But doing a research, finally I found something like this:
public List<Employee> getEmployees() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("ResourcesService");
EntityManager em = factory.createEntityManager();
Query q = em.createQuery("from Employee e", Employee.class);
return q.getResultList();
}
Is there a even more simplified way to query this, just using the class name? Because the mapped entity already contains the select query.
I mean instead of doing this
Query q = em.createQuery("from Employee e", Employee.class);
To do something like this fictional example:
Query q = em.createQuery(Employee.class);
Why not use the named query you have defined?
em.createNamedQuery("Employee.findAll").getResultList();
You could name it "Employee.class" ... :-)
Related
I have two entities
#Entity
public class Language {
#Id
#GeneratedValue
private int id;
private String name;
private String isoCode;
}
and the another entity
#Entity
public class MainEntity {
#Id
#GeneratedValue
private int id;
private String anotherField;
private Language language; //(here I want to return the full entity)
}
The entities don't have a database relation just a string field, Now I want to do a query for MainEntity but I want to get the full entity
For example
Language
value
id
1
name
English
isoCode
EN
MainEntity
value
id
a
name
xyz
language
EN
I have that repository
public interface MainRepository extends JpaRepository<MainEntity, Integer>{
User findAll();
}
but I want that when I do a search on my primary entity it brings me the entire language entity
for example
MyEntity.Language.getName()
Use native query to read JPA objects? See this simplified example where you can use any valid native sql query syntax.
You could put Language getLanguage() function to MainEntity class.
String sql = "Select * From MyEntityTable Where id between (?1 and ?2)";
Query query = entityMgr.createNativeQuery(sql, MyEntity.class);
query.setParameter(1, 1001);
query.setParameter(2, 2002);
List<MyEntity> list = query.getResultList();
If you don't want to make a reletion between MainEntity and Language you have to make a native query. (As is you can't make also a jpql query because you should have at least the String language in the MainEntity in order to make a join on String isoCode in Language but as I understand I think you don't want to do that).
So you have to perform a native query returning an interface as stated here
public interface IntermediateObject {
int getId();
String getName();
int getLanguageId();
String getLanguageName();
String getIsoCode();
}
In the repository:
#Query("select m.id as id, m.name as name, l.id as languageId, l.name as languageName, l.isoCode as isoCode MainEntity m join Language l on m.language = l.isoCode", native=true)
List<IntermediateObject> someMethod();
In the MainEntity or better another dto you have to declare a constructor:
public class AnotherDto {
private int id;
private String name;
private LanguageDto language;
public AnotherDto(int id, String name, int languageId, String languageName, String isoCOde) {
this.id = id;
this.name = name;
this.language = new LanguageDto(languageId, languageName, isoCode);
}
}
public class LanguageDto {
private int id;
private String name;
private String isoCode;
public LanguageDto(int id, String name, String isoCode) {
this.id;
this.name = name;
this.isoCode = isoCode;
}
}
And in the service layer you have to construct AnotherDto from IntermediateObject
public List<AnotherDto> someMethod() {
return repository.someMethod().stream().map(i -> new AnotherDto(i.getId(), i.getName(), i.getLanguageId(), i.getLanguageName(), i.getIsoCode())).collect(Collectors.toList());
}
and now you have the language object populated.
Anyway I suggest to map the entities instead to do all of this.
I am working on a spring boot project and using JPA for querying the database with Entity manager.
i.e.
Query query = entityManager.createNativeQuery("SELECT * FROM TABLE_NAME WHERE ID = 1"); // SUPPOSE
List<Object[]> result = (List<Object[]>) query.getResultList();
now after this what I want to achieve here is creating an Object of that corresponding result.
i.e. ResultObject obj = (ResultObject) result.get(0);
// here ResultObject is user defined.
but this type of casting is not possible directly.
so what I am currently doing is:
ResultObject obj = new ResultObject();
obj.setArribute1((String) obj[0]);
obj.setArribute2((Integer) obj[1]);
...
and on average i will be having 15 attributes per object. so its really tiresome...
I have tried using:
List<ResultObject> obj = (List<ResultObject>)query.getResultList();
but doesn't work.
Either use ConstructorResult (JPA) or ResultTransformer (Hibernate) or QLRM.
ConstructorResult is JPA standard and you have to create a Annotation with the column mapping:
#SqlResultSetMapping(
name = "BookValueMapping",
classes = #ConstructorResult(
targetClass = BookValue.class,
columns = {
#ColumnResult(name = "id", type = Long.class),
#ColumnResult(name = "title"),
#ColumnResult(name = "version", type = Long.class),
#ColumnResult(name = "authorName")}))
From https://thorben-janssen.com/result-set-mapping-constructor-result-mappings/
And ResultTransformer is Hibernate proprietary and you must use the Hibernate session:
List<PersonSummaryDTO> dtos = session.createNativeQuery(
"SELECT p.id as \"id\", p.name as \"name\" " +
"FROM Person p")
.setResultTransformer( Transformers.aliasToBean( PersonSummaryDTO.class ) )
.list();
From https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#sql-dto-query
Or QLRM is a library that maps the result to a DTO using the constructor:
JpaResultMapper jpaResultMapper = new JpaResultMapper();
Query q = em.createNativeQuery("SELECT ID, NAME FROM EMPLOYEE");
List<EmployeeTO> list = jpaResultMapper.list(q, EmployeeTO.class);
https://github.com/72services/qlrm
if you have set up a DatabaseConfig like this tutorial then you can simply create a class that you annotate with #Entity and #Table(name = "yourDatabaseTableName") Don't forget to define:
#Id
#Column(name = "ID")
private Long id;
and annotate all your colums with #Column(name = "databaseColumnName")
Then, create an interface that you annotate with #Repository which extends JpaRepository<YourEntityClass, Long>where the Long-parameter is the type you've given to the id-variable of your Entity.
Now you can use simple JPA-methodqueries like findAll() or you can create your own JPQL-queries like:
#Query("SELECT e FROM Entity e "
+ "WHERE e.id = :id")
Optional<Entity> findById(#Param("id") Long id);
It's even possible to use NativeQueries in this way:
#Query(value = "SELECT e FROM Entity e "
+ "WHERE e.id = :id",
nativeQuery = true)
Optional<Entity> findById(#Param("id") Long id);
Id suggest creating a POJO that can be mapped to your table you're retrieving values from:
#Entity
#Table(name = "MyTable")
#NamedQueries({
#NamedQuery(name = "MyTable.findAll", query = "SELECT m FROM MyTable m")})
public class MyTable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#Column(name = "name")
private String name;
#Basic(optional = false)
#Column(name = "display_name")
private String displayName;
public MyTable() {
}
public MyTable(Integer id) {
this.id = id;
}
public MyTable(Integer id, String name, String displayName) {
this.id = id;
this.name = name;
this.displayName = displayName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof MyTable)) {
return false;
}
MyTable other = (MyTable ) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "MyTable[ id=" + id + " ]";
}
}
Obviously fill in the fields as you need with the corresponding database datatype repersentation.
Notice how i have NamedQueries we can now take advantage of those named queries to do our fetches
TypedQuery<MyTable> query = entityManager.createNamedQuery("MyTable.findAll", MyTable.class);
List<MyTable> results = query.getResultList();
this will do all the casting and conversions for you. You can add all the named queries you want.
https://www.objectdb.com/java/jpa/query/named
UPDATE
If you need to dynamically create a query you can do the following:
String query = "SELECT m FROM MyTable m Where m.id =:id and m.name=:name";
///modify the query as needed based off of other conditions)
TypedQuery<MyTable > query = em.createQuery(query, MyTable .class);
query.setParameter("id", id);
query.setParameter("name", name);
List<MyTable> results = query.getResultList();
https://www.objectdb.com/java/jpa/query/api
I have two models, Owner and Contract. A contract has an instance of an owner, owner does not have a list of contracts. I'm trying to query my list of contracts, to return a list filtered by owner, ie, a list of contracts by owner.
I had tried to follow previous examples and use Criteria to write a custom query, but, following suggestions I've checked the docks and tried to use named queries instead, however, I'm still really struggling.
There was an unexpected error (type=Internal Server Error, status=500).
Named parameter not bound : ownerId; nested exception is org.hibernate.QueryException: Named parameter not bound : ownerId
My models look like this:
#Entity
#Table(name="Contracts")
#NamedQueries({
#NamedQuery(
name = "Contract.allContractsByOwner",
query = "SELECT c FROM Contract c WHERE c.owner.id LIKE :ownerId"
)
})
public class Contract {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#ManyToOne
private Owner owner;
#Column
private double price;
#Column
private String deliverDate;
public Contract(Owner owner, double price, String deliverDate) {
this.id = id;
this.owner = owner;
this.price = price;
this.deliverDate = deliverDate;
}
and
#Entity
#Table(name="Owners")
public class Owner {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column
private String name;
public Owner(String name){
this.name = name;
}
my contractRepoImpl
#Service
public class ContractRepositoryImpl implements ContractRepositoryCustom {
ContractRepository contractRepository;
#Autowired
EntityManager entityManager;
public List allContractsByOwner(Long ownerId) {
List contracts = entityManager.createQuery(
"SELECT c FROM Contract c WHERE c.owner.id LIKE :ownerId", Contract.class)
.getResultList();
return contracts;
}
}
which I name in my ContractRepo and ContractRepoCustom files, and then in my controller I map to it like so. But, when I query it in my browser I get the error in my terminal.
#GetMapping(value="/owners/{ownerId}/contracts")
public List allContractsByOwner(#PathVariable("ownerId") Long ownerId){
return contractRepository.allContractsByOwner(ownerId);
}
I appreciate this is probably beginners mistakes, I am trying to follow docs but get a bit stuck with syntax & where annotations need to go.
Thanks JB Nizet, got there in the end
I added parameters to my contractRepoImpl
#Service
public class ContractRepositoryImpl implements ContractRepositoryCustom {
ContractRepository contractRepository;
#Autowired
EntityManager entityManager;
public List allContractsByOwner(Long id) {
List contracts = entityManager.createQuery(
"SELECT c FROM Contract c WHERE c.owner.id = :ownerId", Contract.class)
.setParameter("ownerId", id)
.getResultList();
return contracts;
}
}
that then produced a SQL error, which I fixed by changing my #NamedQuery from 'LIKE' to '=' in my Contract class...
#NamedQueries({
#NamedQuery(
name = "Contract.allContractsByOwner",
query = "SELECT c FROM Contract c WHERE c.owner.id = :ownerId"
)
})
I am attempting to retrieve a list of results from my database, by following an example in this answer. Howeverm, I keep getting the following error:
java.lang.AbstractMethodError: org.hibernate.ejb.EntityManagerImpl.createQuery(Ljava/lang/String;Ljava/lang/Class;)Ljavax/persistence/TypedQuery;
Here is my code, to denote how I am calling this:
#Entity
#Table(name = "MY_TABLE")
public class CoolsEntity implements Serializable {
#Id
#Column(name = "ID", columnDefinition = "Decimal(10,0)")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
#Column(name = "COOL_GUY_NAME")
private String name;
public String getId() {
return id;
}
public void setId(final String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name= name;
}
}
This code below generates the error:
final String sql = "select c from CoolsEntity c";
final TypedQuery<CoolsEntity> query = em.createQuery(sql, CoolsEntity.class);
final List<CoolsEntity> results = query.getResultList();
return results;
However, if I do something like this, I can see the results:
final String sql = "select c from CoolsEntity c";
final Query query = em.createQuery(sql);
#SuppressWarnings("unchecked")
final List<CoolsEntity> results = query.getResultList();
return results;
All of the references to em are imported through this package:
import javax.persistence.EntityManager
Shouldn't the two queries above generate the same result? Am I missing a cast to the List interface to allow this to work in the typed query?
You have an AbstractMethodError exception which is thrown when an application tries to call an abstract method.
You have quite a mix of Hibernate and JPA versions.
TypedQuery was introduced in JPA 2.0 and Hibernate implements this specification since 3.5.X
Suggesstion : Use implementation from Hibernate version 3.6.3 (or higher).
you are probably using two differnet version of interface EntityManager and implementation EntityManagerImpl.
I have a function that merges two tables, each of these tables has a column that I want to filter.
#Entity
public class Contacts {
#Id
private int id;
#ManyToOne //reference user_id = id
private User user;
#ManyToOne //reference people_id = id
private People people;
//getters and setters
}
#Entity
public class User {
private int id;
private int name;
private Enterprise enterprise;
//getters and setters
}
#Entity
public class People {
private int id;
private int name;
//..others fields
private Enterprise enterprise;
//getters and setters
}
I need to list all "Contacts" where my enterprise id = 1. On a simple select (SQLServer), it will be:
SELECT c.* FROM CONTACTS c
INNER JOIN User u ON u.id = c.user_id
INNER JOIN People p on p.id = p.people_id
WHERE u.empresa_id = 1
I can't figure out how to do it with Criteria API, I already tried the follow code, but I keep receiving an error.
//code..public List<Obj> list(int id) {
Criteria crit = session.createCriteria(Contacts.class);
crit.add(Restrictions.eq(user.enterprise.id, id)); //it doesn't work!
crit.list();
}
org.hibernate.QueryException: could not resolve property: user.enterprise.id of: sys.com.model.Contacts
here i am writing code for sample using criteria.
public List<Student_document> getUserById(int id) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
Student_document.class);
criteria.add(Restrictions.eq("user_document.user_Id", id));
return criteria.list();
}