Spring Data JPA - How to find by param with underscore - spring

Here is my model:
public class Log {
#Id
private String id;
private String project;
private String test_no;
// Constructor, getters and setters.
}
How can I add a findBy query which allows me to finding an element by its test_no value? I have tried those method headers but they don't work:
List<Log> findByTest_No(String test_no);
The error that my STS reports is: Invalid delivery query! No property test found in type Log!
List<Log> findByTest_no(String test_no);
The error that my STS reports is: Invalid delivery query! No property test found in type Log!
List<Log> findByTestno(String test_no);
The error that my STS reports is: Invalid derived query! No property testno found for type Log! Did you mean 'test_no'?

It seems that _ is a special character which separates properties names
... it is possible for the algorithm to select the wrong property ... To resolve this ambiguity you can use \_ inside your method name to manually define traversal points ...
Docs
So it can't find test field in Log class.
Try to use:
#Query("select log from Log log where log.test_no = ?1")
List<Log> findByTestNo(String testNo);

There is no need to use private String test_no; You may use private String testNo; Spring automatically understand that you are binding test_no column in the database. Also you can use
#Column(name = "test_no")
private String testNo;
After this changes you can execute queries, mentioned in your question without any custom sql.
List<Log> findByTestNo(String testNo);

Related

Throw error when properties marked with #JsonIgnore are passed

I have a requirement to mark certain properties in my REST beans as ignored using #JsonIgnore. (I am using Spring Boot). This helps in avoiding these properties in my Swagger REST documentation.
I also would like to ensure that if the client passes these properties, an error is sent back. I tried setting spring.jackson.deserialization.fail-on-unknown-properties=true, but that works only for properties that are truly unknown. The properties marked with #JsonIgnore passes through this check.
Is there any way to achieve this?
I think I found a solution -
If I add #JsonProperty(access = Access.READ_ONLY) to the field that is marked as #JsonIgnore, I get back a validation error. (I have also marked the property with #Null annotation. Here is the complete solution:
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Employee {
#Null(message = "Id must not be passed in request")
private String id;
private String name;
//getters and setters
}
#JsonInclude(JsonInclude.Include.NON_NULL)
public class EmployeeRequest extends Employee {
#Override
#JsonIgnore
#JsonProperty(access = Access.READ_ONLY)
public void setId(String id) {
super.setId(id);
}
}
PS: By adding #JsonProperty(access = Access.READ_ONLY), the property started showing up in Swagger model I had to add #ApiModelProperty(hidden = true) to hide it again.
The create method takes EmployeeRequest as input (deserialization), and the get method returns Employee as response (serialization). If I pass id in create request, with the above solution, it gives me back a ConstraintViolation.
PS PS: Bummer. None of these solutions worked end-to-end. I ended up creating separate request and response beans - with no hierarchical relationship between them.

CRUDRepository findBy foreign key id causing exception: Unable to locate Attribute with the the given name [classroomId] on this ManagedType

I am getting an exception when creating a custom findBy method by a foreign key.
Entity class:
#Entity
#Getter
#Setter
public class Thread {
private #Id #GeneratedValue Long id;
private String subject;
#ManyToOne(fetch = FetchType.LAZY)
#JsonIgnore
private Classroom classroom;
protected Thread() {}
public Long getClassroomId() {
return this.classroom.getId();
}
}
ThreadRepository class:
public interface ThreadRepository extends CrudRepository<Thread, Long> {
List<Thread> findByClassroomId(Long id);
}
I get the exception:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [classroomId] on this ManagedType [com.futurerprood.unicycleservice.entity.threads.Thread]
But the exception goes away if I remove the getClassroomId() in the Thread class. I have this function so that the json serialization will pick up only the classroom id instead of the whole classroom object in an endpoint response.
Why is this function causing the foreign key unable to be found?
You can do one of the following:
Provide the query to the repository method
#Query("select e from Thread t join t.classroom c where c.id = :id")
List<Thread> findByClassroomId(Long id);
Rename the repository method
List<Event> findByClassroom_Id(Long id);
Update
Explanation as to why these two are working
First, have a look at https://docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/htmlsingle/#d0e391 and understand how property traversal based on method name happens in Spring data JPA in order to generate the query and how ambiguity resolution is recommended.
In the first one, we tell spring data, it does not need to do property traversal to generate the JPA query as we are giving the query so it does not get any ambiguity.
In the second, as recommended in the reference, we are resolving the ambiguity for Spring Data JPA by telling it to go to Classroom object first. But as #crizzis pointed out under the question comment, Spring data should have treated it as ambiguity in the first place

How to get recent record by a field and ordered by date (complex query)?

I am trying to write a method in spring data to get last recod by text and ordered by updateDate.
My entity look like :
#Entity
public class Command {
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private String text;
// epoch date
private Long updateDate;
/* Getters and Setters */
}
And this is the repository:
public interface CommandRepository extends JpaRepository<Command, Long> {
Command findByTextAndTopByUpdateDateDesc(String text);
}
Of course, find by text method must give me more thant one reocord but by filtering with top date will get only one record !
the methode above return the following error :
Caused by:
org.springframework.data.mapping.PropertyReferenceException: No
property TopByUpdateDateDesc found for type Command! at
org.springframework.data.mapping.PropertyPath.(PropertyPath.java:94)
I tried to check some stackoverflow postes to find any solution but nada !
Is there any solution to that case or i have to use native query ?
The ordering in your query method is wrong. You first need the limitations (Top/First) before you do the where part and you end with the ordering. This is also what the error, given a bit cryptic, is telling you.
Instead of findByTextAndTopByUpdateDateDesc you should use something like findFirstByTextOrderByUpdateDateDesc.
The ordering etc. is explained in the Spring Data JPA documentation.

findById() gives No property Id found

I have three entities.
(I am using xxx as a place holder for this example)
I have set up all their #Entities with
#Entity
#Table(name = "xxx")
public class xxx {
#Id
#Column(name = "xxx_id")
int xxx_id;
However, I am able to do:
findById(int ...) for only ONE of the entities in their respective Repository.
When I try to do that for the other two entities, I get this problem:
"Invalid derived query! No property id found for type xxx!"
I am able to run it and get the proper results. But why am I getting this error for two entities but not the other?
I set up the entities and their repositories exactly the same way.
The ONLY difference is that in the entity whose repository does not return any errors, I am joining that entity with another entity whose repository fails, but I used "mappedBy" in the #JoinColumns section.
Could that have something to do with why that one has no problems?
How findBy... works?
Entity:
private int clientid;
private String firstname;
private String lastname;
Query:
findBy<Name_as_per_entity>
findByClientid(int clientid);
findByFirstnameAndLastname(String firstname, String lastname)
Solution
Because we treat the underscore character as a reserved character, we
strongly advise following standard Java naming conventions (that is,
not using underscores in property names but using camel case instead).
Doc
The underscore _ is a reserved character in Spring Data query derivation to potentially allow manual property path description.
Stick to the Java naming conventions of using camel-case for member variable names and everything will work as expected.
Also Refer this

spring-data-cassandra, Cassandra storing List<Integer> as field

I have problem storing field of List as field of my table in cassandra database.
I'm using spring-data-cassandra, version 1.4.1.RELEASE.
My model contains:
#Column
#CassandraType(type = DataType.Name.LIST)
private List<Integer> somedata;
I would like to auto create my db tables with SchemaAction.RECREATE_DROP_UNUSED Schema action in my config class:
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.RECREATE_DROP_UNUSED;
}
It tries to create table, but following exception occurs:
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: expected 1 of typed arguments for the property 'somedata' type is 'interface java.util.List' in the entity <my class here>
Ok, found solution after digging into spring-data-cassandra source:
#CassandraType(type = DataType.Name.LIST, typeArguments = { DataType.Name.FLOAT } )
private List<Float> position;
You need to add typeArguments, to specify DataType of generic type. Exception mentioned in question is thrown when invalid number of those typeArguments is passed. In my case there was 0 and 1 is required.
#Column annotation proved to be not required here.
There is no need to provide CassandraType annotation over the field as long as you are using primitive or Wrapper type objects.
Following works fine for me.
#PrimaryKey
int id;
String name;
int num;
List<Integer> marks;
I am using spring-data-cassandra with version 1.4.2.RELEASE.
Please update if you still face the issue.

Resources