There is a little problem in replying on ajax requests. Initially, I have simplest restful service, based on spring boot MVC.
model:
import javax.persistence.*;
import java.util.*;
#Entity
#Table(name = "testmodel")
public class TestModel
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)//Postgresql sequence generator
private long id;
#Column(name = "name")
private String name;
#Column(name = "content")
private String content;
//Constructor
public TestModel()
{
}
//Id getter
public long getId()
{
return this.id;
}
//Name getter-setter
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name = name;
}
//Content getter-setter
public String getContent()
{
return this.content;
}
public void setContent(String content)
{
this.content = content;
}
}
DAO for model:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.*;
public interface TetsModelDAO extends JpaRepository<Samples, Long>
{
#Query("SELECT s FROM TestModel s WHERE LOWER(s.name) LIKE LOWER(:entry) ORDER BY s.name")
List<TestModel> fetchByNameEntry(#Param("entry") String entry);
}
Controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
#RequestMapping("/")
public class TestController
{
#Autowired
private TetsModelDAO testmodel;
#RequestMapping("/name")
public List<TestModel> getDatasetsByNameEntry(#RequestParam("entry") String entry)
{
return testmodel.fetchByNameEntry("%"+entry+"%");
}
}
Client-side ajax request:
$.ajax(
{
url : "/name?entry=", //get all records
method: "GET"
})
This example works perfectly - stringified reply looks like standart json structure:
{"id":"1", "name":"John", "content":"blablabla1"}
{"id":"2", "name":"Sam", "content":"blablabla2"}
{"id":"3", "name":"Ken", "content":"blablabla3"}
However, when I tried to define fileds in JPQL query explicitly (fetch, say, only id and name fields), I get wrong result in reply.
DAO with modified query (other code without changes):
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.*;
public interface TetsModelDAO extends JpaRepository<Samples, Long>
{
#Query("SELECT s.id, s.name FROM TestModel s WHERE LOWER(s.name) LIKE LOWER(:entry) ORDER BY s.name")
List<TestModel> fetchByNameEntry(#Param("entry") String entry);
}
In this case reply looks like this:
1, John, 2, Sam, 3, Ken
How to resolve this problem gracefully (without creating "helper classes")?
You can return DTO directly from Repository:
public interface TetsModelDAO extends JpaRepository<Samples, Long>
{
#Query("SELECT new mypackage.TestDto(s.id, s.name) FROM TestModel s WHERE LOWER(s.name) LIKE LOWER(:entry) ORDER BY s.name")
List<TestDto> fetchByNameEntry(#Param("entry") String entry);
}
where TestDto contains only required fields:
package mypackage;
public class TestDto {
private final long id;
private final String name;
public TestDto(long id, String name) {
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
}
Your query doesn't return instances of TestModel. It returns arrays of objects (i.e. a List<Object[]>), each array containing the ID and the name of a found TestModel. The correct query is
SELECT s FROM TestModel s WHERE LOWER(s.name) LIKE LOWER(:entry) ORDER BY s.name
You'd better implement automated tests to check that your DAO queries return what they should.
Related
I have REST api, and when client call POST request with body, backend after deserialize should distinguish null from the absence of a value.
Because if value in JSON is null, then value in DB should become null.
If value in JSON absence, then value in DB should remain unchanged.
JSON:
{
"id" : 1,
"name" : "sample name",
"value" : null
}
OR
{
"id" : 1,
"name" : "sample name"
}
For Java after deserialization it is look like : value = null;
Java:
#Entity
#Table("sample")
public class Sample {
#Id
#Column
private Long id;
#Column
private String name;
#Column
private Integer value;
// getters / setters
}
Sample REST request:
#PutMapping
public ResponseEntity<SampleDto> updateSample(#RequestBody SampleDto dto) {
return ResponseEntity.ok(service.updateSample(dto));
}
Sample service impl:
public SampleDto updateSample(SampleDto dto) {
Sample sample = sampleRepository.findById(dto.getId);
sample.setName(dto.getName());
sample.setValue(dto.getValue());
//In this operation back need understand: value is null or absence
//Because if value in JSON is null, then value in DB should become null
//If value in JSON absence, then value in DB should remain unchanged
Sample newSample = sampleRepository.save(sample);
return modelMapper.map(newSample, SampleDto.class);
}
Project use Spring Data.
Maybe I should use #JsonDeserialize annotation or other Hibernate annotation
I tried use #JsonDeserialize, but it is not solution.
Partial update is different from full-resource update and we should implement it in a different way. Let's create two request POJO classes. One class will be used to create and update resources, second will be used to partially update given resource. To emphasise it we will use different HTTP methods. To distinguish null from absence we can use java.util.Optional class.
SampleCompleteRequest class we use together with POST (create) and PUT (update) methods.
SamplePartialRequest class we use together with PATCH (partially update) method.
To avoid boilerplate code in this example I'm using Lombok and MapStruct but it is not required.
Model
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
#Data
public class SampleCompleteRequest {
#NotBlank
private String name;
private String value;
}
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.util.Optional;
#Data
public class SamplePartialRequest {
private Optional<#NotBlank String> name;
private Optional<String> value;
}
import lombok.Data;
#Data
public class SampleResponse {
private Long id;
private String name;
private String value;
}
import lombok.Data;
#Data
public class Sample {
//#Id - Hibernate annotations are removed
private Long id;
private String name;
private String value;
}
MapStruct
In MapStruct we need to define an interface with all methods we need.
import com.example.demo.model.SampleCompleteRequest;
import com.example.demo.model.SamplePartialRequest;
import com.example.demo.model.SampleResponse;
import jakarta.annotation.Nullable;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.ReportingPolicy;
import java.util.Optional;
import static org.mapstruct.MappingConstants.ComponentModel.SPRING;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
import static org.mapstruct.NullValuePropertyMappingStrategy.IGNORE;
#Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = SPRING)
public interface SamplesMapper {
#BeanMapping(nullValueCheckStrategy = ALWAYS, nullValuePropertyMappingStrategy = IGNORE)
Sample patch(SamplePartialRequest input, #MappingTarget Sample target);
Sample update(SampleCompleteRequest input, #MappingTarget Sample target);
SampleResponse mapToResponse(Sample input);
default String optionalToString(#Nullable Optional<String> nullable) {
return nullable == null ? null : nullable.orElse(null);
}
}
Plugin will generate boilerplate code for us. Below class is autogenerated and we do not need to implement it manually.
#Component
public class SamplesMapperImpl implements SamplesMapper {
#Override
public Sample patch(SamplePartialRequest input, Sample target) {
if ( input == null ) {
return target;
}
if ( input.getName() != null ) {
target.setName( optionalToString( input.getName() ) );
}
if ( input.getValue() != null ) {
target.setValue( optionalToString( input.getValue() ) );
}
return target;
}
#Override
public Sample update(SampleCompleteRequest input, Sample target) {
if ( input == null ) {
return target;
}
target.setName( input.getName() );
target.setValue( input.getValue() );
return target;
}
#Override
public SampleResponse mapToResponse(Sample input) {
if ( input == null ) {
return null;
}
SampleResponse sampleResponse = new SampleResponse();
sampleResponse.setId( input.getId() );
sampleResponse.setName( input.getName() );
sampleResponse.setValue( input.getValue() );
return sampleResponse;
}
}
Resource
A controller class is easy to implement:
import com.example.demo.model.SampleCompleteRequest;
import com.example.demo.model.SamplePartialRequest;
import com.example.demo.model.SampleResponse;
import com.example.service.SamplesMapper;
import com.example.service.SamplesService;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#AllArgsConstructor
#RestController
#RequestMapping(value = "/api/v1/samples")
public class SamplesResource {
private final SamplesMapper mapper;
private final SamplesService samplesService;
#GetMapping
public CollectionModel<SampleResponse> listAll() {
List<SampleResponse> entities = samplesService.list().stream().map(mapper::mapToResponse).toList();
return CollectionModel.of(entities);
}
#PostMapping
public EntityModel<SampleResponse> addSample(#Valid #RequestBody SampleCompleteRequest request) {
var entity = samplesService.create(request);
var response = mapper.mapToResponse(entity);
return EntityModel.of(response);
}
#PutMapping(path = "{id}")
public EntityModel<SampleResponse> updateSample(#PathVariable Long id, #Valid #RequestBody SampleCompleteRequest request) {
var entity = samplesService.update(id, request);
var response = mapper.mapToResponse(entity);
return EntityModel.of(response);
}
#PatchMapping(path = "{id}")
public EntityModel<SampleResponse> partiallyUpdateSample(#PathVariable Long id, #Valid #RequestBody SamplePartialRequest request) {
var entity = samplesService.patch(id, request);
var response = mapper.mapToResponse(entity);
return EntityModel.of(response);
}
}
A service class is also straightforward:
import com.example.demo.model.SampleCompleteRequest;
import com.example.demo.model.SamplePartialRequest;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
#AllArgsConstructor
public class SamplesService {
private final SamplesMapper mapper;
private final SamplesRepository repository;
public List<Sample> list() {
return repository.listAll();
}
public Sample create(SampleCompleteRequest request) {
var sample = mapper.update(request, new Sample());
return repository.save(sample);
}
public Sample update(Long id, SampleCompleteRequest request) {
var sample = repository.find(id).orElseThrow();
mapper.update(request, sample);
return repository.save(sample);
}
public Sample patch(Long id, SamplePartialRequest request) {
var sample = repository.find(id).orElseThrow();
mapper.patch(request, sample);
return repository.save(sample);
}
}
See also:
HTTP PUT vs HTTP PATCH in a REST API
Difference between Jackson objectMapper to others
Spring MVC PATCH method: partial updates
I'm using SpringBoot to communicate with MongoDB. I've made 2 models the first one is Events:
package backend.blabla.model;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Document
#Data
public class Events {
private String name;
private String ProjectId;
public Events(
String name,
String ProjectId) {
this.name= name;
this.ProjectId = ProjectId;
}
}
and the second one is EventList which contains an arrayList of Events:
package backend.blabla.model;
import java.util.ArrayList;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Document
#Data
public class EventList {
#Id
private String id;
private String name;
private String projectId ;
public ArrayList<Events> events;
public EventList(String name,String projectId,ArrayList<Events> events){
this.name= name;
this.projectId = projectId;
this.events= new ArrayList<Events>();
}
}
so I can obtain the following structure
[
{
"id"="62a10a455238454587911d9d",
"name":"xxxxx",
"projectId":"62998dadb89ca15c88d6880a",
"events":[
{
"name":"to do",
"ProjectId":"62998dadb89ca15c88d6880a"
},
{
"name":"done",
"ProjectId":"62998dadb89ca15c88d6880a"
}
]
}
]
And I have this method in the controller to add a new event in the arrayList events for a certain EventList
#PutMapping("/{id}")
EventList addEvent(#PathVariable String id,#RequestBody Events event){
EventList eventListFromDB = eventListRepo.findById(id).orElseThrow(RuntimeException::new);
Events newEvent = new Events(event.getName(), event.getProjectId());
ArrayList<Events> eventsFromDB = eventListFromDB.getEvents();
eventsFromDB.add(newEvent);
eventListFromDB.setEvents(eventsFromDB);
return eventListRepo.save(eventListFromDB);
}
The problem that I'm facing is when I try to add a new event the old one gets removed and when I made
System.out.println(eventListFromDB)
before the
eventsFromDB.add(newEvent);
it gives me
EventList(id=62a10a455238454587911d9d, name=xxxxx, projectId=62998dadb89ca15c88d6880a, events=[])
and after it it gives me
EventList(id=62a10a455238454587911d9d, name=xxxxx, projectId=62998dadb89ca15c88d6880a, events=[Events(name=to do,ProjectId=62998dadb89ca15c88d)])
First question is how to extract data from the arrayList
and second how can I add to the arrayList without removing the first arrayList's element
which I believe if the first question get answered the second automatically will too
and thanks in advance
enter image description hereI am new to Spring Boot Data JPA repository. This is my first application with JPA. I am trying to get data from DB. But which returns NULL.
Entity File
import javax.persistence.*;
#Entity
#Table(name = "TASK_DETAILS")
public class TaskDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "TASK_DETAILS_ID")
private long taskDetailsId;
#Column(name = "TASK_NAME")
private String TaskName;
#Column(name = "TASK_POLLING_TIME")
private int TaskTime;
#Column(name = "TASK_FILE")
private String TaskClassFile;
#Column(name = "TASK_STATUS")
private String TaskStatus;
public long getTaskDetailsId() {
return taskDetailsId;
}
public void setTaskDetailsId(long taskDetailsId) {
this.taskDetailsId = taskDetailsId;
}
public String getTaskName() {
return TaskName;
}
public void setTaskName(String taskName) {
TaskName = taskName;
}
public int getTaskTime() {
return TaskTime;
}
public void setTaskTime(int taskTime) {
TaskTime = taskTime;
}
public String getTaskClassFile() {
return TaskClassFile;
}
public void setTaskClassFile(String taskClassFile) {
TaskClassFile = taskClassFile;
}
public String getTaskStatus() {
return TaskStatus;
}
public void setTaskStatus(String taskStatus) {
TaskStatus = taskStatus;
}
}
Repository File
import java.util.Collection;
import java.util.List;
import java.util.Optional;
#Repository
public interface TaskDetailsRepository extends JpaRepository<TaskDetails, String> {
TaskDetails findByTaskDetailsId(final long id);
}
My Main Method
#Service
public class ImportAmazonData {
#Autowired
private TaskDetailsRepository taskDetailsRepositoryDAO;
public void getProductsFromAmazonStore(JobExecutionContext context) throws ClassNotFoundException {
final long taskID = (long) context.getJobDetail().getJobDataMap().get("taskId");
TaskDetails taskDetails = taskDetailsRepositoryDAO.findByTaskDetailsId(taskID);
System.out.println("Result : " + taskDetails.getTaskClassFile());
}
}
ProductSync File
import com.example.Schedular.AmazonSync.ImportAmazonData;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
public class ProductSync implements Job {
#Autowired
private ImportAmazonData importAmazonData;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
importAmazonData.getProductsFromAmazonStore(context);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Here i am trying to get the TaskDetails by id. But my taskDetailsRepositoryDAO was null. Here i have attached my error log. Please let me know. Thanks in advance.
ERROR LOG
java.lang.NullPointerException: null
at com.example.Schedular.AmazonSync.ImportAmazonData.getProductsFromAmazonStore(ImportAmazonData.java:20) ~[classes/:na]
at com.example.Schedular.SyncData.ProductSync.execute(ProductSync.java:16) ~[classes/:na]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.2.jar:na]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.3.2.jar:na]
In your repository file i.e TaskDetailsRepository should be as below :
import java.util.Collection;
import java.util.List;
import java.util.Optional;
#Repository
public interface TaskDetailsRepository extends JpaRepository<TaskDetails, Long> {
Optional<TaskDetails> findByTaskDetailsId(Long id);
}
Use wrappers instead of primitives in your domain classes.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "TASK_DETAILS_ID")
private Long taskDetailsId;
If your are trying to find a record on basis of a particular value then specify that type i.e. Long.
And always use Optional if your method is going to return a sing record from database. this will help you resovle NullPointers.
This might help you.
Try adding this in your spring boot main file(I think it is SchedularApplication)
#EnableJpaRepositories("your jpa repository package name")
i need to update tow columns inside my table (Job this table is joint with two other tables employees and job-history)one of them is the primary key, but i get error, if someone can help.
package com.touati.org.model;
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.List;
/**
* The persistent class for the jobs database table.
*
*/
#Entity
#Table(name="jobs")
#NamedQuery(name="Job.findAll", query="SELECT j FROM Job j")
public class Job implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="JOB_ID")
private String jobId;
#Column(name="JOB_TITLE")
private String jobTitle;
#Column(name="MAX_SALARY")
private BigDecimal maxSalary;
#Column(name="MIN_SALARY")
private BigDecimal minSalary;
//bi-directional many-to-one association to Employee
#OneToMany(mappedBy="job")
private List<Employee> employees;
//bi-directional many-to-one association to JobHistory
#OneToMany(mappedBy="job")
private List<JobHistory> jobHistories;
public Job() {
}
public String getJobId() {
return this.jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getJobTitle() {
return this.jobTitle;
}
public void setJobTitle(String jobTitle) {
this.jobTitle = jobTitle;
}
public BigDecimal getMaxSalary() {
return this.maxSalary;
}
public void setMaxSalary(BigDecimal maxSalary) {
this.maxSalary = maxSalary;
}
public BigDecimal getMinSalary() {
return this.minSalary;
}
public void setMinSalary(BigDecimal minSalary) {
this.minSalary = minSalary;
}
public List<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public Employee addEmployee(Employee employee) {
getEmployees().add(employee);
employee.setJob(this);
return employee;
}
public Employee removeEmployee(Employee employee) {
getEmployees().remove(employee);
employee.setJob(null);
return employee;
}
public List<JobHistory> getJobHistories() {
return this.jobHistories;
}
public void setJobHistories(List<JobHistory> jobHistories) {
this.jobHistories = jobHistories;
}
public JobHistory addJobHistory(JobHistory jobHistory) {
getJobHistories().add(jobHistory);
jobHistory.setJob(this);
return jobHistory;
}
public JobHistory removeJobHistory(JobHistory jobHistory) {
getJobHistories().remove(jobHistory);
jobHistory.setJob(null);
return jobHistory;
}
}
my controller: here when i try to look for all job in the data base it works fine, also if i try to update juste the title of the job it works fine to but in case that i try to set a new primary key for the job table it gives me error here my controller.
package com.touati.org.model;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
#Controller // This means that this class is a Controller
#RequestMapping(path="/project") // This means URL's start with /demo (after Application path)
public class MainController {
#GetMapping(path="/job")
public #ResponseBody Iterable<Job> getAllJob() {
// This returns a JSON or XML with the users
return jobRepository.findAll();
}
#GetMapping(path="/job/{jobId}")
public #ResponseBody String getJob(#PathVariable String jobId) {
Job job = jobRepository.findOne(jobId);
try {
job.setJobTitle("manager");
job.setJobId("test1");
jobRepository.save(job);
}
catch (Exception ex) {
return "Error updating the job: " + ex.toString();
}
return "Job succesfully updated!";
}
}
i got this error,
Error updating the user: org.springframework.orm.jpa.JpaSystemException: identifier of an instance of com.touati.org.model.Job was altered from test to test1; nested exception is org.hibernate.HibernateException: identifier of an instance of com.touati.org.model.Job was altered from test to test1
Thank you for your help.
Primary key should never be changed. If you need to change primary key it means your design is bad. If you need to change JOB_ID often then create another column for your primary key like ID. Another possibility is to copy all attributes and create new record with new JOB_ID and then remove old one.
I am getting error "Cannot create TypedQuery for query with more than one return using requested result type"
I tried with all columns value returning. That time the application hangs. I need to get list of Client, in arraylist. Please help, I am new to JPA.
#Override
public ArrayList<Client> findAllClients() {
EntityManager entity = this.emf.createEntityManager();
List<Client> clients = entity.createQuery("select clientID,clientName from Client", Client.class).getResultList();
return (ArrayList<Client>) clients;
}
Client class is
package com.springmaven.models;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="tblclient")
public class Client {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY) #Column(name="ntClientID")
private Long clientId;
#Column(name="vcClientName")
private String clientName;
#Column(name="vcLocation")
private String location;
#Column(name="ofstTimeZone")
private Date timeZone;
#Column(name="vcCommunicationMode")
private String communicationMode;
#Column(name="vcContact")
private String contact;
#OneToMany(targetEntity=Project.class,mappedBy="client",
cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private Set<Project> projects = new HashSet<Project>();
public Set<Project> getProjects() {
return projects;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
public Long getClientId() {
return clientId;
}
public void setClientId(Long clientId) {
this.clientId = clientId;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Date getTimeZone() {
return timeZone;
}
public void setTimeZone(Date timeZone) {
this.timeZone = timeZone;
}
public String getCommunicationMode() {
return communicationMode;
}
public void setCommunicationMode(String communicationMode) {
this.communicationMode = communicationMode;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public Client(){
}
}
Usually on Hibernate you simply make selects of an specific entity, not necessarily defining what columns you want. Something like this:
List<Client> clients = entity.createQuery("select c from Client c", Client.class).getResultList();
You are getting the TypedQuery error because the EntityManager is waiting for a collection of Clients, but instead you are selecting two specific columns of it, which will make Hibernate unable to cast the results as a Client entity.
So in your case, use the query given above and everything should work fine.
You can cast to your result in (List< clients >)
List<Client> clients = (List<Client>) entity.createQuery("select clientID,clientName from Client", Client.class).getResultList();
That is a projection query on the "client" thay only return clientID and clientName, instead of loading the full object to memory. This approach can allow to reduce network traffic to the database server and save memory.
So, you can use the next one:
List<Object[]> results =
entity.createQuery("select clientID, clientName from Client").getResultList();
This result set contains a List of Object arrays and each array represents one set of properties, in this case clientID and clientName. Now you can retrieved this:
Object[] o = results.get(0); // for first element!
Long id = (Long) o[0]; // choose the correct type!
String name = (String) o[1];