2

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")?

2 Answers 2

2

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;
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate class [TestDto] [SELECT new TestDto(s.id, s.name) FROM TestModel s WHERE LOWER(s.name) LIKE LOWER(:entry) What is this? Class TestDto in the same package as TestDAO
You have to specify fully name of your class (including package) in @Query - just added it to my answer
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.