This is Controller Code
#PutMapping
#PreAuthorize("hasRole('USER')")
#RequestMapping("/update")
public ResponseEntity<?> userUpdate(MemberDto memberDto){
memberService.userUpdate(memberDto);
return new ResponseEntity<>("ok", HttpStatus.OK);
}
This is my Member Class code
#Entity
#Getter
#Setter
#Table(name = "member")
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class Member {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
private String email;
private String password;
private String providerId;
#Enumerated(EnumType.STRING)
private MemberRole role;
#Enumerated(EnumType.STRING)
private AuthProvider authProvider;
private String imageUrl;
//추가
private String phoneNumber;
#CreationTimestamp
private LocalDateTime createTime;
#UpdateTimestamp
private LocalDateTime updateTime;
#JsonIgnore
#OneToMany(mappedBy = "member")
private List<Post> posts = new ArrayList<>();
#JsonIgnore
#OneToMany(mappedBy = "member")
private List<Save> save = new ArrayList<>();
// #JsonIgnore
// #OneToMany(mappedBy = "member")
// private List<Follow> follow = new ArrayList<>();
#JsonIgnore
#OneToMany(mappedBy = "member")
private List<Image> image = new ArrayList<>();
}
This is DTO code
#Data
#NoArgsConstructor
public class MemberDto {
private Long id;
private String email;
private String password;
private String name;
private String phoneNumber;
#QueryProjection
public MemberDto(Long id, String email, String password, String name, String phoneNumber){
this.id = id;
this.email = email;
this.password=password;
this.name = name;
this.phoneNumber = phoneNumber;
}
}
This is Service Code
#RequiredArgsConstructor
#Service
public class MemberService {
#Autowired
private MemberRepository memberRepository;
public void userUpdate(MemberDto updateValue) {
memberRepository.updateMember(updateValue);
}
}
This is Repository(impl) code
#RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom {
private final EntityManager em;
private final JPAQueryFactory queryFactory;
#Override
public void updateMember(MemberDto memberDto){
QMember qMember = QMember.member;
queryFactory.update(qMember)
.where(qMember.id.eq(memberDto.getId()))
.set(qMember.email, memberDto.getEmail())
.set(qMember.password, memberDto.getPassword())
.set(qMember.name, memberDto.getName())
.set(qMember.phoneNumber, memberDto.getPhoneNumber())
.execute();
}
}
And This is my frontend (react)code send as json
{id: 7, name: '111', email: '111#111.com1', password: '12313', phonenumber: '123123'}
email: "111#111.com1"
id: 7
name: "111"
password: "12313"
phonenumber: "123123"
I try to update myDB use member ID As you can see use querydsl with
.where(qMember.id.eq(memberDto.getId()))
This code in Repository class
so I expecte nativequery like
email: "111#111.com1"
id: 7
name: "111"
password: "12313"
phonenumber: "123123"
update member(tablename) set name = 111, password = 123123, ..... where id = 7
But querydsl throw Error
java.lang.IllegalArgumentException: eq(null) is not allowed. Use isNull() instead
I Think my code is something wrong but I can't find it.
And also chrome console throw error
error: "Internal Server Error"
path: "/user/update"
status: 500
timestamp: "2021-10-12T21:04:00.658+00:00"
Internal server error so I confident that my backend Code is wrong
please help me
Related
When I save any data, it'll save in id 4,14,24,etc. I want it to be in order like 1,2,3. Here is my code.
#Entity#Data#Table(name = "user") #NoArgsConstructor #AllArgsConstructor public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idUser")
private Long idUser;
#Column(name = "name")
private String name;
#Column(name = "dob")
private Date DOB;
#Column(name = "address")
private String address;
#UpdateTimestamp
#Column(name = "updated_at")
private Date updatedAt;
#Column(name= "updated_by")
private String updatedBy;
#CreationTimestamp
#Column(name = "created_at")
private Date createdAt;}
Here is my DTO
#Data public class UserDTO {
private long idUser;
private String name;
private Date DOB;
private String address;
private Date updated_at;
private Date created_at;}
Here is my Service
#Slf4j #Service #AllArgsConstructor #NoArgsConstructor #Transactional public class UserService {
#Autowired
private UserRepository userRepository;
public User save( User request) {
return userRepository.save(request);
}}
I only include some code in question so it will not be too long, but my code is like the one I use in photo.
Here is the return from get:
the IDs are 4 and id 14
Thank you in advance
Edit: I just found that the Id starts with 4 as default from addons ClearDB from heroku that I use
I have a simple API, built with Spring Boot, where I am trying to convert entity classes to the corresponding dtos.
Student Entity
#Entity(name = "students")
#AllArgsConstructor
#Getter
#Setter
public class Student extends AbstractUpdatable<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "student_id")
private Long id;
#Column(name = "student_first_name", nullable = false)
#NotNull(message = "First name is mandatory")
private String firstName;
#Column(name = "student_last_name", nullable = false)
#NotNull(message = "Last name is mandatory")
private String lastName;
#Column(name = "student_ssn", unique = true, nullable = false)
#NotNull(message = "SSN is mandatory")
#Size(min = 10, max = 10)
private String ssn;
#Column(name = "student_age")
#Min(5)
#Max(100)
private Integer studentAge;
#Column(name = "student_email")
#Email
private String email;
#Column(name = "student_level")
private Integer studentLevel; // TODO could be enum or separate entity
#Column(name = "student_creation_date")
private Date creationDate; // TODO check spring's feature to manage creation and update dates (auditing)
#ManyToOne
#JoinColumn(name = "group_id")
private Group group;
public Student() {
this.creationDate = new java.util.Date(); // TODO this will be removed when spring's auditing is utilized
}
}
Group Entity
#Entity(name = "groups")
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
public class Group extends AbstractUpdatable<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id")
private Long id;
#Column(name = "group_name")
private String Name;
#OneToMany(mappedBy = "group")
#JsonIgnore
private List<Student> students;
}
Student DTO
public class StudentDto extends AbstractStudentDto implements Serializable {
private final Long id;
private final Date creationDate;
public StudentDto(String firstName, String lastName, String email, Long id, GroupDto group, Integer studentAge, Integer studentLevel,
Date creationDate) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.group = group;
this.studentAge = studentAge;
this.studentLevel = studentLevel;
this.creationDate = creationDate;
}
public Long getId() {
return id;
}
public Date getCreationDate() {
return creationDate;
}
}
Group DTO
public class GroupDto extends AbstractGroupDto{
private final Long id;
public GroupDto(Long id, String name, List<StudentDto> students) {
this.id = id;
this.name = name;
this.students = students;
}
public Long getId() {
return id;
}
}
GroupToGroupDtoConverter
#Component
public class GroupToGroupDtoConverter implements org.springframework.core.convert.converter.Converter<Group, GroupDto> {
private final ConversionService conversionService;
#Autowired
public GroupToGroupDtoConverter(ConversionService conversionService) {
this.conversionService = conversionService;
}
#Override
public GroupDto convert(Group source) {
var convertedStudents = new ArrayList<StudentDto>();
if (!CollectionUtils.isEmpty(source.getStudents())) {
source.getStudents().forEach(student ->
convertedStudents.add(conversionService
.convert(student, StudentDto.class)));
}
return new GroupDto(source.getId(), source.getName(), convertedStudents);
}
}
And a very similar StudentToStudentDtoConverter.
The issue is that when the code needs to do the conversion from any of the entities to their dtos I get
org.springframework.core.convert.ConverterNotFoundException: No
converter found capable of converting from type
[com.studentmanagement.model.Group] to type
[com.studentmanagement.dto.group.GroupDto]
Now if I try to remove the conversion of the students' list to a list of student dtos in the converter above, so the converter looks like this:
#Component
public class GroupToGroupDtoConverter implements org.springframework.core.convert.converter.Converter<Group, GroupDto> {
#Override
public GroupDto convert(Group source) {
return new GroupDto(source.getId(), source.getName(), new ArrayList<StudentDto>());
}
}
The conversion works with no issues (with a dummy students list of course). Am I missing something when I am adding the conversion service inside my converters?
I tried to replicate the issue and did a small working demo on this.
One thing I found while doing that, that could be relevant to your case, is that injecting a conversion service into a converter is not trivial (see e.g. this and this relevant issues).
Also, important as well, do not forget to register the converters, as shown below on the code samples, and e.g. here. From the error message you posted, seems like the service cannot find the needed converter.
For my demo, please note I removed the group field from the StudentDTO class to simplify things. I hope it helps, happy to share the full code as well in github.
I used the following converter for Group:
#Component
public class GroupToGroupDtoConverter implements org.springframework.core.convert.converter.Converter<Group, GroupDto> {
private ConversionService conversionService;
public GroupToGroupDtoConverter(ConversionService conversionService) {
this.conversionService = conversionService;
}
#Override
public GroupDto convert(Group group) {
List<StudentDto> studentDtoList =
group.getStudents().stream().map(a -> conversionService.convert(a, StudentDto.class)).collect(Collectors.toList());
GroupDto groupDto = new GroupDto(group.getId(), group.getName(), studentDtoList);
return groupDto;
}
}
But in order to successfully inject the conversion service and register the converters I added this:
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Autowired
#Lazy
ConversionService conversionService;
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new GroupToGroupDtoConverter(conversionService));
registry.addConverter(new StudentToStudentDtoConvervter());
}
}
If, for example, I comment out the first addConverter line, I get the Converter not found exception:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.example.conversion_entities.Group] to type [com.example.conversion_entities.GroupDto]
Once all is done, the following test passes:
#RunWith(SpringRunner.class)
#SpringBootTest
class GroupToGroupDtoConverterTest {
#Autowired
ConversionService conversionService;
#Test
void convert() {
Student studentA = new Student();
studentA.setFirstName("John");
studentA.setLastName("Doe");
Student studentB = new Student();
studentB.setFirstName("Jane");
studentB.setLastName("Doe");
List<Student> studentList = new ArrayList<>();
studentList.add(studentA);
studentList.add(studentB);
Group group = new Group(1L, "groupA", studentList);
GroupDto convertedGroupDto = conversionService.convert(group, GroupDto.class);
assertEquals("John", convertedGroupDto.getStudents().get(0).getFirstName());
assertEquals("Jane", convertedGroupDto.getStudents().get(1).getFirstName());
}
}
I think the problem is ConversionService can't convert your classes by default. Instead try to inject a class implementing ConversionService with correct convert method implementation inside.
I have REST api with User model - DTO and Create / update form. My userService checks if user is administrator, then allow to getAllUsers in List. When I want to get all users, I get Bad request 400, but it should return Forbidden. It used to work but when I added some changes to my code I got bad request. I don't know what I'm missing...
My User.java
///Lombok annotations
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Setter(AccessLevel.NONE)
#Column(unique = true)
private Long id;
#Setter(AccessLevel.NONE)
#EqualsAndHashCode.Include
#Column(nullable = false, unique = true)
private UUID uuid = UUID.randomUUID();
#Column(unique = true, nullable = false, length = 254)
private String login;
#Column(nullable = false, length = 254)
private String firstName;
#Column(nullable = false, length = 254)
private String lastName;
#Enumerated(EnumType.STRING)
private RoleType roleType;
#Column(nullable = false, length = 254)
private String password;
#Email
#Column(nullable = false, length = 254)
private String email;
#Positive
private Double cost;
public User(String login, String firstName, String lastName, RoleType roleType, String password,
String email, Double cost) {
this.login = login;
this.firstName = firstName;
this.lastName = lastName;
this.roleType = roleType;
this.password = password;
this.email = email;
this.cost = cost;
}
UserController
#GetMapping("users")
public ResponseEntity<List<UserDto>> getAllUsers(#RequestParam UUID uuid) {
return userService.getListResponseEntity(uuid);
}
UserService
public ResponseEntity<List<UserDto>> getListResponseEntity(UUID adminUuid) {
if (authService.adminAuth(adminUuid)) {
List<User> users = userRepo.findAll();
List<UserDto> userDto = users
.stream()
.map(user -> userMapper.mapToUserDto(user))
.collect(Collectors.toList());
return new ResponseEntity<>(userDto, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
}
UserDto
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class UserDto {
private String login;
private String firstName;
private String lastName;
private RoleType roleType;
private String email;
private Double cost;
I think you missed uuid parameter in request header.
It will be like this. http://localhost:8080/users?uuid="enter_your_uuid_here"
There could be changes that your JSON request data is not matching with you DTO data fields.
Validate following points in your JSON request
there could be issue of wrong field Name
may be not sending proper data as per the datatype.
I'm using a query in my spring boot project with hard coded values and that is fine:
#Query("select user from Users user where user.mobileNumber=?1 and not user.status=-2")
Users FindNotDeletedUserByMobileNumber(String MobileNumber);
But, I wanted to use not hardcoded values, eg. reading from an enum, I tried this :
#Query("select user from Users user where user.mobileNumber=?1 and not user.status=com.taxikar.enums.User_Status.Deleted")
Users FindNotDeletedUserByMobileNumber(String MobileNumber)
But this one gives error while building :
'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract com.taxikar.entity.Users com.taxikar.repository.UserRepository.FindNotDeletedUserByMobileNumber(java.lang.String)!
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
I use this enum values in my other classes and they are working fine, for example:
if (user.getStatus() == User_Status.Deleted.getId())
return new BaseResponse(BR_Status.error.getId(), BR_ErrorCodes.NotAuthorizedUser.getStringValue() + "01",
"error 755", user.getId());
Even using .getId or .getStringValue like the one above but at end of my query doesn't solve anything. What am I doing wrong ?
Here is my enums code :
public enum User_Status implements IResponse
{
Deleted(-2),
Unauthorized(-1),
NotCompleteGeneralInfo(0),
CompleteGeneralInfo(1);
private int value;
private String stringValue;
User_Status(int value)
{
this.value = value;
}
User_Status(String stringValue){this.stringValue=stringValue;}
#Override
public int getId()
{
return value;
}
#Override
public String getStringValue()
{
return stringValue;
}
}
This enum implements IResponse which is like this :
public interface IResponse
{
String getStringValue();
int getId();
}
Here Is my repository :
public interface UserRepository extends JpaRepository<Users, String>
{
#Query("select user from Users user where user.mobileNumber=?1 and not user.status=com.taxikar.enums.User_Status.Deleted")
Users FindNotDeletedUserByMobileNumber(String MobileNumber);
}
And here is my entity class :
#Entity
#Table(name = "users")
public class Users
{
// these fields are feed by us not the user
#Id
#GeneratedValue(generator = "uuid2")
#Column(columnDefinition = "char(36)")
#GenericGenerator(name = "uuid2", strategy = "uuid2")
private String id;
#Column(name = "STATUS") // User status ===>-2: Deleted , -1: unauthorized , 0: user info is not complete , 1: complete user
private int status;
#Column(name = "RATE")
private String rate;
//Not Optional fields
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
#Column(name = "SEX") // Sex ====> 1:women 2:men
private int sex;
#Column(name = "MOBILE_NUMBER")
private String mobileNumber;
#Column(name = "USER_IMG")
private String userImg;
#Column(name = "IDENTITY_NUMBER")
private String identityNumber;
#Column(name = "USER_IDENTITY_CARD_IMG")
private String userIdentityCardImg;
//Optional fields
#Column(name = "EMAIL")
private String email;
#Column(name = "BIRTHDAY")
private String birthday;
#Column(name = "DESCRIPTION")
private String description;
// not Optional fields for driver
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "DRIVER_DETAIL")
private DriverDetail driverDetail;
//Login related fields
#Column(name = "TOKEN")
private String token;
#Column(name = "TOKEN_TIMESTAMP")
private Timestamp tokenTimeStamp;
#Column(name="SMS_COUNT")
private int smsCount;
#Column(name="SMS_COUNT_TIMESTAMP")
private Timestamp smsCountTimeStamp;
+++ constructor and setters and getters.
}
Try this:
#Query("select user from Users user where user.mobileNumber=?1 and user.status<>?2")
Users FindNotDeletedUserByMobileNumber(String MobileNumber, int status);
and pass in -2 as parameter when you call that repository method
So lets say I have User object like this
#Entity
public class User {
#Id
#GeneratedValue
private long id;
private String name;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "address", referencedColumnName = "id")
private Address address;
}
#Entity
public class Address {
#Id
#GeneratedValue
private long id;
private String city;
private String country;
}
Now I don't want to write validation annotations in entities. What I would like to do is validate User in #RestController like this
#RestController
public class InvoiceController {
#RequestMapping(value="/users/add", method = RequestMethod.POST)
public Invoice addInvoice(#Validated #RequestBody ValidUser user) {
... do stuff
}
}
The validation annotations would be in ValidUser being like this.
public class ValidUser extends User {
#NotNull
private String name;
#Valid
private Address address;
}
public class ValidAddress extends Address{
#NotNull
private String city;
#NotNull
private String country;
}
The validation works when I remove the address field from the ValidUser but not when it is there. How can I make address validation also work?