Nested property not found in a Spring Data query method declaration - spring

I'm trying to use findBy... in my repository to get a Savingaccount object passing a nested attribute(name) as a parameter. Currently I'm using:
Mono<SavingAccount> findByOwnerName(String name);
but I'm getting this error: No property name found for type Owner! Traversed path: SavingAccount.owner.
My repository:
package com...SavingAccMS.Repository;
import com.everis.SavingAccMS.Model.Owner;
import com.everis.SavingAccMS.Model.SavingAccount;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Mono;
public interface SavingAccountRepo extends ReactiveMongoRepository<SavingAccount, String>
{
Mono<SavingAccount> findByNumber(String number);
//This one is the problem
Mono<SavingAccount> findByOwnerName(String name);
Mono<SavingAccount> findByOwner(Owner owner);
}
My Entity:
package com...SavingAccMS.Model;
import java.security.acl.Owner;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "SavingAccs")
public class SavingAccount
{
#Id
private String id;
#NotBlank
private String number;
#NotBlank
private Owner owner;
#NotBlank
private String currency;
#NotBlank
private double balance = 0.00;
#NotBlank
private String status;
}
package com...SavingAccMS.Model;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "Owners")
public class Owner
{
public String dni;
public String name; //findBy this attribute is required.
}

According to your imports, the Owner in your SavingAccount refers to java.security.acl.Owner, not the one you defined yourself in om...SavingAccMS.Model.Owner. The former does not carry a name attribute.

I'm not certain but I don't think you can find the owner name in hibernate like that.
I would try the following!
#Query("SELECT * FROM SavingAccount where owner.name = :name")
Mono<SavingAccount> findByOwnerName(#Param("name") String name);

Related

Handle Date data type with spring data ldap

I am using spring-data-ldap to find all the users who are created or modified in a certain date range. My UserRepository
package com.test.service.ldap.com;
import org.springframework.data.ldap.repository.LdapRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface UserRepository extends LdapRepository<User> {}
My User class
package com.test.service.ldap.com;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.domain.Persistable;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.odm.annotations.Transient;
import javax.naming.Name;
import java.util.Date;
#Entry(base = "ou=people,dc=example,dc=com",objectClasses = { "top","person","organizationalPerson","inetOrgPerson" })
#Data
#ToString
public final class User implements Persistable<Name> {
private #Id Name id;
private #Attribute(name = "cn") String firstname;
private #Attribute(name = "sn") String lastname;
private #Attribute(name = "mobile") String mobile;
private #Attribute(name = "createTimestamp") Date createdtime;
private #Attribute(name = "modifyTimestamp") Date modifiedtime;
#Transient
private Boolean isNew = false;
#Override
public boolean isNew() {
return isNew;
}
}
I get the below exception when I try to findAll()
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '20221229074251.850Z'
at org.springframework.core.convert.support.ObjectToObjectConverter.convert(ObjectToObjectConverter.java:117)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
at org.springframework.ldap.odm.typeconversion.impl.ConversionServiceConverterManager.convert(ConversionServiceConverterManager.java:67)
...
...
I want to know
How to handle Date data type in spring-data-ldap
Can I use something like findAllOrderByModifiedTimeDesc or use Between two dates

No property .. found for type .. in spring boot

I'm a beginner with spring and I have this little issue. "No property questionId found for type CourseTestCompleteField!" I have 2 model classes that are connected via a one to one join.
That 2 model class are:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "questions")
public class CourseTestQuestion {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="question_id")
private Long id;
#NotBlank
#Column(name = "question_course")
private String questionCourse;
#NotBlank
#Column(name = "question_type")
private String questionType;
public CourseTestQuestion(){
}
public CourseTestQuestion(String questionCourse, String questionType) {
this.questionCourse = questionCourse;
this.questionType = questionType;
}
// public getters and setters for all fields here
}
And:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "quiz_complete_field_questions",
uniqueConstraints = {
#UniqueConstraint(columnNames = "question_id")
}
)
public class CourseTestCompleteField {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "question_content")
private String questionContent;
#NotBlank
#Column(name = "answer")
private String answer;
#NotBlank
#Column(name = "points")
private String points;
#NotBlank
#Column(name = "course")
private String course;
#NotBlank
#Column(name = "teacher_username")
private String teacher;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "question_id", referencedColumnName = "question_id")
private CourseTestQuestion courseTestQuestion;
public CourseTestCompleteField(){
}
public CourseTestCompleteField(CourseTestQuestion courseTestQuestion, String question, String answer, String points, String course, String teacher) {
this.courseTestQuestion = courseTestQuestion;
this.questionContent = question;
this.answer = answer;
this.points = points;
this.course = course;
this.teacher = teacher;
}
// public getters and setters for all fields here
}
My repo for both:
package com.example.springboot.repository;
import com.example.springboot.models.Course;
import com.example.springboot.models.CourseTestQuestion;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface CourseTestQuestionRepository extends JpaRepository<CourseTestQuestion, Long> {
Optional<CourseTestQuestion> findById(Long id);
Optional<CourseTestQuestion> findByQuestionCourse(String questionCourse);
}
And:
package com.example.springboot.repository;
import com.example.springboot.models.CourseTestCompleteField;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
#Repository
public interface CourseTestCompleteFieldRepository extends JpaRepository<CourseTestCompleteField, Long> {
Optional<CourseTestCompleteField> findById(Long id);
Optional<CourseTestCompleteField> findByQuestionId(Long questionId);
Optional<CourseTestCompleteField> findByCourse(String course);
List<CourseTestCompleteField> findByQuestionContent(String questionContent);
List<CourseTestCompleteField> findByTeacher(String teacher);
Boolean existsByQuestionContent(String questionContent);
}
The problem is with Optional<CourseTestCompleteField> findByQuestionId(Long questionId);but I don't get it why, because in database I have the table for CourseTestCompleteFieldModel with question_id column, and in CourseTestCompleteField I have CourseTestQuestion object. Tho, the table for CourseTestCompleteField has a different name, could be this a problem? I should rename the table to course_test_complete_field?
Can someone help me please? Thank you
Since,This is a query on nested Object. You need to update your query as this.
Optional<CourseTestCompleteField> findByCourseTestQuestion_Id(Long questionId);
This works even without "_"
Optional<CourseTestCompleteField> findByCourseTestQuestionId(Long questionId);
But better to put "_" while accessing nested fields for better readability.
There is no field call questionId in you entity and you have id only.
That's you got error. You can use that findyById(). That's only enough.
If you would like write JPA repository method like findBy..., getBy..., deleteBy...., countBy..., After this you need append exact field name from entity.
For example if you entity have name then can write below methods. findByName(); deleteByName(); countByName();
So try as below.
findBycourseTestQuestion(Object o);
Pass questions object.

Problem Parsing request body of type json, containing a list of string to Flux of string in Spring reactive

I have a DTO as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Flux;
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackageDto {
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<String> packageAttributes;
private Flux<String> extras;
}
And a Database Object as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import reactor.core.publisher.Flux;
#Document("internet_packages")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackage {
#Id
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<StoreableAttribute> attributes;
private Flux<StoreableAttribute> extras;
}
The StorableAttribute Database Model like so:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document("package_attributes")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class StoreableAttribute {
#Id
private String id;
private String name;
private String description;
}
On the Data Object the fields: Flux<StoreableAttribute> attributes and Flux<StoreableAttribute> extras are stored in a separate collection alongside the Package Object. And is handled by the mapper as below:
public InternetPackage fromDto(InternetPackageDto dto) {
var internetPackage = new InternetPackage();
internetPackage.setName(dto.getName());
internetPackage.setPrice(dto.getPrice());
internetPackage.setId(dto.getId());
internetPackage.setExtras(this.resolePackageExtras(dto));
internetPackage.setAttributes(this.resolePackageAttributes(dto));
return internetPackage;
}
private Flux<StoreableAttribute> resolePackageExtras(InternetPackageDto dto) {
return this.storeableAttributeService.resolveAttributes(dto.getExtras());
}
for the extra and similarly for the attributes also.
And a simple controller method as below:
#PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public Mono<InternetPackageDto> update(#RequestBody InternetPackageDto incomingPackageDto) {
return this.packageService
.updatePackage(this.dtoMapper.fromDto(incomingPackageDto))
.map(this.dtoMapper::toDto);
}
And when I make a post request I get an error stating
org.springframework.core.codec.CodecException: Type definition error: [simple type, class reactor.core.publisher.Flux]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `reactor.core.publisher.Flux` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (io.netty.buffer.ByteBufInputStream); line: 2, column: 13] (through reference chain: com.example.api.dto.InternetPackageDto["extras"])
Some more information:
I am using the class InternetPackageDto as a request object as well as a response object.
I am using Flux<String> and not List<String> since I wasn't sure if doing blocking resolution to list was a good idea.
The attributes are stored and managed separately.
And during the time of updating or inserting the package those; if a new extra or attribute is included the attributes collection in db will be updated with the insertion of new incoming extras and attributes.
It seems like I might have made a stupid mistake because I cannot find much information about this problem, or I am doing it completely wrong.
Any help would be greatly appreciated.
I think you should do smth like this
public Mono<InternetPackageDto> toDto(InternetPackage entity) {
var internetPackage = new InternetPackageDto();
internetPackage.setName(entity.getName());
internetPackage.setPrice(entity.getPrice());
internetPackage.setId(entity.getId());
return Mono.zip(Mono.just(internetPackage), entity.getExtras().collectList(), entity.getAttributes().collectList())
.flatMap(tu->{
var dto = tu.getT1();
dto.setExtras(tu.getT2()); //To make it work in my local i made entity.getAttributes() as Flux<String> so here you will probably need to use .stream().map(dbItem->dbItem.getPropertyName())
dto.setPackageAttributes(tu.getT2());
return Mono.just(dto);
});
}

Superclass Fields Using #Builder Lombok

WHow to fetch the Superclass fields in the builder?
Parent:
package com.goomo.sso.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
#AllArgsConstructor
#NoArgsConstructor
#Data
public class BaseResponseModel implements Serializable {
private static final long serialVersionUID = 1L;
private String status;
private StatusMessage statusMessage;
}
Child:
package com.goomo.sso.dto;
import java.io.Serializable;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
#Data
#EqualsAndHashCode(callSuper=false)
#ToString
public class UserRequest extends BaseResponseModel implements Serializable {
private static final long serialVersionUID = 1L;
private String clientName;
private String role;
private String groupName;
private String userName;
#Builder
public UserRequest(String status, StatusMessage statusMessage, String clientName, String role, String groupName,
String userName) {
super(status,statusMessage);
this.clientName = clientName;
this.role=role;
this.groupName=groupName;
this.userName = userName;
}
}
I couldn't get the fields of the parent class in the builder. Can you please suggest me the correct way of achieving it?

How to write query by using findBy..() methods for one record

I've an entity class User_Details
package vl.cybersecurityapplication.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "User_Details")
public class User_Details implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "UserId")
private int userId;
#Column(name = "FirstName")
private String firstName;
#Column(name = "LastName")
private String lastName;
#Column(name = "Password")
private String password;
#Column(name = "E_Mail")
private String eMail;
#Column(name = "Mobile_Num")
private int mobileNumber;
//getters and setters
}
Here is my repo interface
package vl.cybersecurityapplication.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import vl.cybersecurityapplication.model.User_Details;
public interface IUserRepository extends JpaRepository<User_Details, Long> {
public Integer findMobileNumberByName(String userName);
}
This is my repo class
package vl.cybersecurityapplication.repository;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import vl.cybersecurityapplication.model.User_Roles;
#Transactional
#Repository
public class UserRepository{
#Autowired
IUserRepository userRepository;
public Integer findMobileNumberByName(#PathVariable String lastName) {
int mobileNumber = userRepository.findMobileNumberByName("shaik");
System.out.println("Mobile Number : "+mobileNumber);
return mobileNumber;
}
}
I'm new to Spring Boot and JPA.
Here I need to query mobile number in User_Details table by using lastname.
i.e., Select Mobile_Num from User_Details where LastName= "xyz";
Can Some one help me how to wo write this query in my repo class.
You can write like this. But you cannot fetch only MobileNumber. You will get a complete object.
List<User> findByLastName(String lastname).
If you want to get only some fields then you should check out Projections
No need to use a native query. JPA supports object based query.
You can use List findByLastName(String lastname) which will generate that query in the backend and return the result.

Resources