Unable to update Data to DB : org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations - spring

i was trying to update database tables by using following Hibernate Query Language
#RequestMapping(value = "/update",method = RequestMethod.POST)
public #ResponseBody String update(#RequestParam(value = "score1",required = true) String score1,
#RequestParam(value = "score2",required = true) String score2,
#RequestParam(value = "score3",required = true) String score3,
#RequestParam(value = "score4",required = true) String score4,
#RequestParam(value = "id",required = true)String id,
Model model)
{
SessionFactory sessionFactory=new Configuration().configure("hibernate.cfg.xml")
.addAnnotatedClass(User.class)
.addAnnotatedClass(UserDetail.class)
.addAnnotatedClass(UserScores.class).buildSessionFactory();
Session session=sessionFactory.getCurrentSession();
try
{
System.out.println("ID is"+id);
session.beginTransaction();
session.createQuery("update UserScores u set " +
"u.score1=:score1," +
"u.score2=:score2," +
"u.score3=:score3," +
"u.score4=:score4 where u.ID=:id")
.setParameter("score1",score1)
.setParameter("score2",score2)
.setParameter("score3",score3)
.setParameter("score4",score4)
.setParameter("id",id);
session.getTransaction().commit();
session.close();
}
catch (Exception e)
{
System.out.println(e);
}
return score1+score2+score3+score4;
}
after executing this code, it doesnt give any error , but the data is not updated in the database
what is the problem in executing this code

Its working, i tried it in another way
#RequestMapping(value = "/update",method = RequestMethod.POST)
public #ResponseBody String update(#RequestParam(value = "score1",required = true) String score1,
#RequestParam(value = "score2",required = true) String score2,
#RequestParam(value = "score3",required = true) String score3,
#RequestParam(value = "score4",required = true) String score4,
#RequestParam(value = "id",required = true)String id,
Model model)
{
SessionFactory sessionFactory=new Configuration().configure("hibernate.cfg.xml")
.addAnnotatedClass(User.class)
.addAnnotatedClass(UserDetail.class)
.addAnnotatedClass(UserScores.class).buildSessionFactory();
Session session=sessionFactory.getCurrentSession();
try
{
session.beginTransaction();
System.out.println("ID is"+id);
UserScores userScores=session.get(UserScores.class,Integer.parseInt(id));
userScores.setScore1((Double.parseDouble(score1)));
userScores.setScore2((Double.parseDouble(score2)));
userScores.setScore3((Double.parseDouble(score3)));
userScores.setScore4((Double.parseDouble(score4)));
session.update(userScores);
session.getTransaction().commit();
session.close();
}
catch (Exception e)
{
System.out.println(e);
}

The query that you are creating needs to be executed using query.executeUpdate()
session.beginTransaction();
Query query = session.createQuery("update UserScores u set " +
"u.score1=:score1," +
"u.score2=:score2," +
"u.score3=:score3," +
"u.score4=:score4 where u.ID=:id");
query.setParameter("score1",score1)
query.setParameter("score2",score2)
query.setParameter("score3",score3)
query.setParameter("score4",score4)
query.setParameter("id",id);
query.executeUpdate();
session.getTransaction().commit();
session.close();
An alternative way is to make changes to the persistent entities. In this case the updates will be automatically propogated.

Related

ServiceResponse mocked which gives a null value and not expected this null

I'm writing j-unit Test-cases for my services and in which i couldn't mock service Response properly, Which is giving me a null. can somebody help me in this issue.
public ResponseEntity<Void> lockGet(
#ApiParam(value = "Unique identifier for this request.", required = true) #RequestHeader(value = "service-id", required = true) String serviceId,
#ApiParam(value = "Logged in userid.", required = true) #RequestHeader(value = "user-id", required = true) String userId,
#ApiParam(value = "Unique messageid.", required = true) #RequestHeader(value = "message-id", required = true) String messageId,
#RequestHeader(value = "access-token", required = true) String accessToken,
#ApiParam(value = "Unique id of the doamin of the entity", required = true) #RequestParam(value = "lockDomainId", required = true) Long lockDomainId,
#ApiParam(value = "Unique id of the entity to be fetched", required = true) #RequestParam(value = "lockEntityId", required = true) Long lockEntityId,
HttpServletRequest request, HttpServletResponse response) {
ResponseEntity<Void> result = null;
if (request.getAttribute("user-id") != null)
userId = (String) request.getAttribute("user-id");
String logContext = "||" + lockDomainId + "|" + lockEntityId + "||";
ThreadContext.put("context", logContext);
long t1 = System.currentTimeMillis();
LOG.info("Method Entry: lockGet" + logContext);
ServiceRequest serviceRequest = AppUtils.mapGetRequestHeaderToServiceRequest(serviceId, userId, lockDomainId,
lockEntityId);
try {
ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
// set all the response headers got from serviceResponse
HeaderUtils.setResponseHeaders(serviceResponse.getResponseHeaders(), response);
result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
} catch (Exception ex) {
LOG.error("Error in lockGet", ex);
result = new ResponseEntity<Void>(HttpStatus.INTERNAL_SERVER_ERROR);
}
ThreadContext.put("responseTime", String.valueOf(System.currentTimeMillis() - t1));
LOG.info("Method Exit: lockGet");
return result;
}
#Test
public void testLockGetForError() {
request.setAttribute("user-id","TestUser");
ServiceRequest serviceRequest = new ServiceRequest();
serviceRequest.setUserId("TestUser");
ServiceResponse serviceResponse = new ServiceResponse();
LockService service = Mockito.mock(LockService.class);
when(service.getLock(serviceRequest)).thenReturn(serviceResponse);
// ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
ResponseEntity<Void> result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
ResponseEntity<Void> lockGet = lockApiController.lockGet("1234", "TestUser", "TestMessage", "TestTkn", 12345L, 12345L, request, response);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, lockGet.getStatusCode());
}
I tried in different scenario's which couldn't fix this issue. Can someone help me out. Thanks in advance.
From the code that you have put , the issue that i see is that you are actually mocking the LockService object but when calling the lockApiController.lockGet method the code is not actually working with the mocked LockService since lockApiController has an LockService object of it's own.
One way to solve this issue is to inject the mocked LockService
object into the lockApiController object using #Spy. This way
when the getLock() is called it will be actually called on the
mocked object and will return the mock response provided.
So in your test :
#Test
public void testLockGetForError() {
LockService service = Mockito.mock(LockService.class);
LockApiController lockApiController = Mockito.spy(new LockApiController(service));
request.setAttribute("user-id","TestUser");
ServiceRequest serviceRequest = new ServiceRequest();
serviceRequest.setUserId("TestUser");
ServiceResponse serviceResponse = new ServiceResponse();
when(service.getLock(serviceRequest)).thenReturn(serviceResponse);
// ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
ResponseEntity<Void> result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
ResponseEntity<Void> lockGet = lockApiController.lockGet("1234", "TestUser", "TestMessage", "TestTkn", 12345L, 12345L, request, response);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, lockGet.getStatusCode());
}
So you can try passing the mocked LockService object to the spy object.
Another way is to try using the #InjectMocks to inject the mocked
object into the LockApiController.
#InjectMocks marks a field on which injection should be performed. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection – in this order. If any of the given injection strategy fail, then Mockito won’t report failure.
For example:
#Mock
Map<String, String> wordMap;
#InjectMocks
MyDictionary dic = new MyDictionary();
#Test
public void whenUseInjectMocksAnnotation_thenCorrect() {
Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning");
assertEquals("aMeaning", dic.getMeaning("aWord"));
}
For the class:
public class MyDictionary {
Map<String, String> wordMap;
public MyDictionary() {
wordMap = new HashMap<String, String>();
}
public void add(final String word, final String meaning) {
wordMap.put(word, meaning);
}
public String getMeaning(final String word) {
return wordMap.get(word);
}
}
For both of these to work , you must be having a constructor or appropriate setters to set the mock object to the LockApiController class.
Reference : https://howtodoinjava.com/mockito/mockito-annotations/

Can I use `#Cacheable` in a Controller?

I want to cache my database access but I have no Repositories. This is how I'm doing (please don't ask why. This is not the point here):
#RequestMapping(value = "/database", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public List<User> testDatabaseCache( #RequestParam("username") String userName ) {
Object[] params = new Object[] { userName };
String sql = "select * from public.users where user_name = ?";
List<User> users = jdbcTemplate.query(sql, params, new UserMapper() );
log.info("Database hit: " + userName);
return users;
}
So... since I have no repository to annotate as cacheable, what can I do?

Spring API #RequestParam Input conversion

I am creating a method for an API. In this method i have some parameters that are optional. those are filters for searching an event. when i try to run it and type the following url:
http://localhost:8181/api/events?id=gRDHzDh9TdiLDAZgrZc2wg==
i get this error message:
Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'; nested exception is java.lang.IllegalArgumentException: Invalid UUID string: gRDHzDh9TdiLDAZgrZc2wg==
So i understand that i insert a String in my url and expect a UUID in code, but how do i convert this? Below here is my code:
#RequestMapping(
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity getEvents(#RequestParam(value = "id", required = false) UUID eventId,
#RequestParam(value = "title", required = false) String title,
#RequestParam(value = "playtype", required = false) PlayType playType,
#RequestParam(value = "skilllevel", required = false) SkillLevel skillLevel,
#RequestParam(value = "sporttype", required = false) SportType sportType,
#RequestParam(value = "long", required = false) String _long,
#RequestParam(value = "lat", required = false) String lat) {
try {
List<Event> events = eventService.getEvents(eventId, title, playType, skillLevel, sportType, _long, lat);
if (events.size() == 0) {
return new ResponseEntity("No events found", HttpStatus.OK);
}
return new ResponseEntity(events, HttpStatus.OK);
} catch (Exception ex){
return new ResponseEntity(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
So here are my 2 questions:
How do i convert the string to a valid UUID input in the RequestParam?
How do i convert the string to a valid enum in the RequestParam? (because with the enums i have the same error)
EDIT
my code is now like this:
#RequestMapping(
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity getEvents(#RequestParam(value = "id", required = false) String eventId,
#RequestParam(value = "title", required = false) String title,
#RequestParam(value = "playtype", required = false) String playType,
#RequestParam(value = "skilllevel", required = false) String skillLevel,
#RequestParam(value = "sporttype", required = false) String sportType,
#RequestParam(value = "long", required = false) String _long,
#RequestParam(value = "lat", required = false) String lat) {
UUID id = null;
PlayType playType1 = null;
SkillLevel skillLevel1 = null;
SportType sportType1 = null;
try {
if (eventId != null){
id = UUID.fromString(eventId);
}
if (playType != null){
playType1 = PlayType.valueOf(playType);
}
if (skillLevel != null){
skillLevel1 = SkillLevel.valueOf(skillLevel);
}
if (sportType != null){
sportType1 = SportType.valueOf(sportType);
}
List<Event> events = eventService.getEvents(id, title, playType1, skillLevel1, sportType1, _long, lat);
if (events.size() == 0) {
return new ResponseEntity("No events found", HttpStatus.OK);
}
return new ResponseEntity(events, HttpStatus.OK);
} catch (Exception ex){
return new ResponseEntity(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
but i still get an error:
Invalid UUID string: gRDHzDh9TdiLDAZgrZc2wg==
How do I convert the string to a valid UUID input?
You need to use UUID.fromString() API, see here
How do i convert the string to a valid enum?
You need to use Enum.valueOf() API, see here

Spring Rest Issue

I am getting an error while i am trying to test my "testCreateUser" method using Spring RestApi, the uploadNewUser.xml contains the login information about the user and the role.
#Test
public void testCreateUser() throws Exception {
Reader reader = getFileReader("src/test/resources/uploadNewUser.xml");
String input_xml = IOUtils.toString(reader);
byte[] content = input_xml.getBytes();
request.addHeader("Accept", "application/xml");
request.addHeader("Content-Type", "application/xml");
request.setContent(content);
request.setContentType("text/xml");
request.setMethod(RequestMethod.POST.name());
request.setRequestURI("/restapi/users/");
final ModelAndView mav = handle(request, response);
Map<String, Object> map = mav.getModel();
for (Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
UserCollection collection = (UserCollection) entry.getValue();
org.springframework.validation.BindingResult.error = com.xxx.dashboard.restapi.GlobalResponse#42a4fd6d
error stack:
java.lang.ClassCastException: com.xxx.dashboard.restapi.GlobalResponse cannot be cast to com.xxx.dashboard.restapi.UserCollection
and i am getting an issue with cannot cast GlobalRespose to UserCollection. can anyone tell me where exactly i am doing is wrong? any help or pointers are most welcome thanks in advance
#Controller("userrestapi")
#RequestMapping(value = { "/restapi/users/", "/restapi/users" })
public class UserRestApi extends AbstractBaseApi {
...
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.CREATED)
public ModelAndView createNewUser(#RequestBody UserCollection userCollection,
#RequestHeader(value = "accept", required = false) String accept,
#RequestHeader(value = "version", required = false) String version) {
try {
OOUser ooUser = userCollection.getUsers().get(0);
Mapper mapper = (Mapper) userVersions.get(Constants.USER_DETAIL_VERSION_MAPPER_KEY);
int userId = usersRestApiService.validateAndCreateNewUser(ooUser, mapper);
List<FilterField> filterFieldList = new ArrayList<FilterField>();
filterFieldList.add(new FilterField("userId", String.valueOf(userId)));
return getUserDetailsForFilter(filterFieldList, accept, version, mapper);
} catch (Exception ex) {
logger.warn("Api exception", ex);
return getModelAndView(accept, "error", getGlobalResponse(ex));
}
the abstractbaseapi contains following
public class AbstractBaseApi {
public static final String XML_VIEW = "apiXmlView";
public static final String JSON_VIEW = "apiJsonView";
public static final String JSON_ACCEPT_HEADER = "application/json";
public static final String JSON_CONTENT_HEADER = "Content-type: application/json";
public static final String XML_CONTENT_HEADER = "Content-type: text/html;charset=utf-8";
public static final int MAX_COUNT = 100;
public static final String XML_REQUEST_ERROR_FORMAT = "<?xml version='1.0' encoding='UTF-8'?><GlobalResponse xmlns='http://www.operative.com/api' xmlns:v2='http://www.operative.com/api/v2' xmlns:v1='http://www.operative.com/api/v1'> <error errorCode='%1$s' text='%2$s'/> </GlobalResponse>";
public static final String JSON_REQUEST_ERROR_FORMAT = "{error:{errorCode:'%1$s',text:'%2$s'}}";
protected final Logger logger = Logger.getLogger(this.getClass());
protected ModelAndView getModelAndView(String accept, String key, Object value) {
String view = XML_VIEW;
if (accept != null && accept.toLowerCase().contains(JSON_ACCEPT_HEADER)) {
view = JSON_VIEW;
}
if (logger.isDebugEnabled()) {
logger.debug("Accept Header:" + accept + " , generating:" + view);
}
return new ModelAndView(view, BindingResult.MODEL_KEY_PREFIX + key, value);
}
Your model contains more than you think.
You are going through your model and looking for your user collection. However, the first encountered object in your map seems to be the GlobalResponse map.
You should probably just get it by name from the model, i.e.
UserCollection collection = (UserCollection) mav.getModel().get("userCollection");
rather than iterating..

Type cast issue for [Ljava.lang.Object

public List<Client> findClientByAssociateUser(String userId) {
logger.info("Enter find list of clients by this user");
org.hibernate.Query query = sessionFactory.getCurrentSession()
.createQuery("SELECT c.id, c.clientName, c.billingAddress,c.contactNumber"
+ " from Client c, User ud"
+ " WHERE ud.id = c.userId and ud.id = :id")
.setString("id", userId);
List<Client> result = (List<Client>) query.list();
logger.info("Exit find list of clients");
return result;
}
public ModelAndView userDetails(#PathVariable String id, HttpServletRequest request) {
ModelAndView mvc = new ModelAndView();
List<Client> clientList = userRepository.findClientByAssociateUser(id.toString());
mvc.addObject("clientList", clientList);
for (Client client : clientList) {
System.out.println("Client Name{" + client.getClientName());
}
mvc.setViewName(MANAGEUSER_PREFIX + "details");
return mvc;
}
I am getting:
Ljava.lang.Object; cannot be cast to Client
The return type in the query would be List<Object[] >.
Because your query says
SELECT c.id, c.clientName, c.billingAddress,c.c......
change
List<Client> result = (List<Client>) query.list();
and then process according to that
to
List<Object[]> result = (List<Object[]>) query.list();
or change the query to
SELECT c from Client c......

Resources