How to store enum data as Array List in a database using Kotlin - spring-boot

I have an enum class that contain multiple data ,I want to store that
enum data as list in database. for example Developer table it contain
technology column ,that column store enum data, Suppose one user want
to store Developer1 working on many technologies like java , Kotllin ,
.Net etc these technologies are belongs from enum class , How to store
.
Same as I have a Subject enum class that contain multiple subject name
,When I Register a new teacher then I want to store how many subjects
teacher know ,If he know multiple subjects that present in our enum
class list then store the subjects id which known by the teacher.But I
am not able to store multiple data in a single column in subjectId ,It
store only one Data in SubjectId column,If I pass multiple data in
subjectId column in postman it throws error 400
teacherEntity class
package com.nilmani.jpqlprojectexample.entity
import com.nilmani.jpqlprojectexample.enum.Subject
import com.nilmani.jpqlprojectexample.enum.University
import java.util.*
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
#Entity
data class Teacher(
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
val id:Long=-1,
val nameOfTeacher:String="",
val price:Long=-1,
val subject:Int = Subject.MATH.type,//List<Int> = listOf(Subject.MATH.type)
val university:Int=University.OTHER.type
)
Subject enum class
package com.nilmani.jpqlprojectexample.enum
enum class Subject(val type:Int) {
MATH(1),
PHYSIC(2),
ACCOUNTING(3),
ZOOLOGY(4),
BIOLOGY(5),
PROGRAMMING(6),
STATICS(7),
CHEMISTRY(8),
HISTORY(9)
}
ReqTeacher Model class
package com.nilmani.jpqlprojectexample.model.request
import com.nilmani.jpqlprojectexample.enum.Subject import com.nilmani.jpqlprojectexample.enum.University
data class ReqTeacher(
val nameOfTeacher:String="",
val price:Long=-1,
val subject:Int= Subject.MATH.type,
val university:Int= University.OTHER.type, )
Response Teacher Model class
package com.nilmani.jpqlprojectexample.model.response
import com.nilmani.jpqlprojectexample.enum.Subject
import com.nilmani.jpqlprojectexample.enum.University
data class ResTeacher(
val nameOfTeacher:String="",
val price:Long=-1,
val subject:Int= Subject.MATH.type,
val university:Int= University.OTHER.type,
)
Teacher controller class
package com.nilmani.jpqlprojectexample.controller
import com.nilmani.jpqlprojectexample.entity.Teacher
import com.nilmani.jpqlprojectexample.model.request.ReqTeacher
import com.nilmani.jpqlprojectexample.model.response.ResTeacher
import com.nilmani.jpqlprojectexample.repository.TeacherRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
#RestController
#RequestMapping("/teachTest")
class TeacherController {
#Autowired
private lateinit var teachRopo:TeacherRepository
#PostMapping("/add")
fun addTeacher(#ModelAttribute request:ReqTeacher):ResponseEntity<*>{
// val newTeacher = teachRopo.findById(request.)
var newTeacher = Teacher(
nameOfTeacher = request.nameOfTeacher,
price = request.price,
subject = request.subject,
university = request.university,
)
val saveTeacher = teachRopo.save(newTeacher)
val respTeacher = ResTeacher(
saveTeacher.nameOfTeacher,
saveTeacher.price,
saveTeacher.subject,
saveTeacher.university
)
return ResponseEntity(respTeacher,HttpStatus.OK)
}
}
I want to store multiple data or single data in SubjectId column of a
particular teacherId,But My code store only one data for a particular
teacherId

You should have a new table (Entity) that represents the 1-to-many relationship between Teacher and Subject, e.g. teacher_subject. This is the proper approach. If you attempt to store the subjects as space/comma-separated values in a single cell, e.g. "math, physics, biology" that would be bad practice.

Related

How to handle this Type MisMatch found List required Entity spring Boot JPA

I create a some operations in my controller class ,I want to store
the results what i get from the operation but when I store these list
of things it show me an error like Below
Type mismatch.
Required:
DepositMaterial!
Found:
List<Result>
Here is my controller class
#PatchMapping("/pendingValue")
fun pend(#ModelAttribute request:ReqFindPending):ResponseEntity<*>{
val existingWithdraw = depositRepository.findPendingByWithDrawId(request.withDrawId)
if (existingWithdraw != null){
val upPending = depositRepository.getPending(withDrawId = request.withDrawId)
depositRepository.save(upPending)
return ResponseEntity(ResMessage("Pending update successfull"),HttpStatus.OK)
}else{
return ResponseEntity(ResMessage(" id getting null value"),HttpStatus.NOT_ACCEPTABLE)
}
}
My repository
package com.nilmani.workload.repository
import com.nilmani.workload.entity.DepositMaterial
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.bind.annotation.RequestParam
interface DepositRepository : JpaRepository<DepositMaterial, Long> {
#Query("SELECT wm.quantity ,dd.totalDeposit,wm.quantity -dd.totalDeposit AS pending FROM WithdrawMaterial wm INNER JOIN DepositMaterial dd ON wm.id = dd.withDrawId ")
fun getPending(#Param("withDrawId")withDrawId: Long?):List<Result>
}
Here is my result Model
data class Result(
val pending: Long,
val quantity: Long,
val totalDeposit: Long
)
DepositMaterial Entity Class
package com.nilmani.workload.entity
import com.nilmani.workload.enum.Material
import java.time.LocalDateTime
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
#Entity
data class DepositMaterial (
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
val id:Long=-1,
val withDrawId:Long=-1,
val totalDeposit:Long=-1,
val material:Int= Material.NONE.type,
val depositTime:LocalDateTime = LocalDateTime.now(),
val pending:Long = -1,
val isDeposited:Boolean=false,
)
What is the reason for this issue,I want to only return these three
things, and store the result subtraction result of totalDeposit and
quantity in pending column to update the table but , It give me error
to store the depositMaterial
You are returning a list of Results from getPending, not an individual DepositMaterial. But the save method requires a single object to save. Try only requesting one object from getPending by changing the return signature.
depositRepository.getPending
returns a list of Entities.
depositRepository.save(upPending)
takes a single Entity to save in the database.
Solution:
Either change your save(upPending) method to saveAll(upPending), or update your getPending repo method to return a unique Entity object.

loadUserByUsername overrides nothing in springboot authentication

I am new to microservice. I want to access username(email)and password
from another service which is userregistration service. when I create
a authentication service and try to access email password I am
getting compile time error.
e: E:\Nil Projects\NewMicroService\security-service\src\main\kotlin\com\security\securityservice\service\JwtUserDetailsService.kt: (16, 5): 'loadUserByUsername' overrides nothing
Here is the my codes
jwtuserdetailsservice.kt
package com.security.securityservice.service
import com.security.securityservice.UserRepository
import com.security.securityservice.entity.User
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.stereotype.Service
#Service
class JwtUserDetailsService {
#Autowired
private lateinit var userDTO:UserRepository
#Throws(Exception::class)
override fun loadUserByUsername(email: String?): UserDetails {
val user: User =userDTO.findUserByEmail(email)
if (userDTO == null){
UsernameNotFoundException("your email id doesn't exist" + email)
}
return org.springframework.security.core.userdetails.User(user.userId.email,user.userId.password,ArrayList())
}
}
Above i define user.userId.email and user.userId.password because I
define userId in my User.kt . this userId comes from
userRegistration-service, this id holds username and password, but I
am not able to access email and password in authentication servicie I
am getting error at this particular point "return
org.springframework.security.core.userdetails.User(user.userId.email,user.userId.password,ArrayList())"
User.kt
package com.security.securityservice.entity
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
#Entity
data class User(
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
val userAuthId:Long=-1,
val otp:Int=0,
val token:String="",
var userId:Long=-1,
)
ResponseTemplate.kt
package com.security.securityservice.VO
import com.security.securityservice.entity.User
data class ResponseTemplate(
val user:User?=null,
val userRegistration: UserRegistration?=null,
)
UserRegistration.kt
package com.security.securityservice.VO
data class UserRegistration(
val userId:Long=-1,
val firstName:String="",
val lastName:String="",
val email:String="",
)
This has nothing to do with microservice instead with simple OOPs programming.
When you say the child class override certain behaviour then it must have one before, which in your case is None. Looking closely at the definition of the class JwtUserDetailsService there is no parent class/neither any interface present hence there is nothing to override. So line
override fun loadUserByUsername(email: String?): UserDetails {
will never compile. I think you should be implementing* the interface here to provide the behaviour UserDetailsService. You see that loadUserByUsername comes from the interface UserDetailsService
Now the code may compile but in order to make authentication work correctly, you have to properly integrate with the authentication manager.

How to write HQL to query the data also include the bridge table column?

I have a question regarding how to write HQL query the data and also contain the bridge table column? Here is my ER diagram:
In my TeamRepository code:
package com.crmbackend.allService.teamService.repo;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import com.crmbackend.entity.Team;
public interface TeamRepository extends PagingAndSortingRepository<Team, Integer> {
#Query("select t from Team t")
public List<Team> getAllTeamandDetails();
}
And here is the result:
As you can see I get all teams and all users who belong to that team.
But question here I can't get the extra column - active from team_users entity.
How should I write this HQL code to extra all team and users information and also the data from bridge table?
That's my question, thanks!
The only way to access this column is to map the collection/join table as entity and also map that column. If you are using Hibernate 5.1+ you can write a query like this:
select t, tu
from Team t
left join TeamUser tu on tu.team.id = t.id

No value passed for parameter

I use kotli. I define everything as per requirement, why I am getting
thing type of Issue
UserRegistrationService.kt: (25, 36): No value passed for parameter 'userRegistration'
I got this type of issue at my UserRegistration class No value passed
for parameter department, and userRegistration
I Creat ResponseTemplateVO POJO Class
ResponseVO.kt
package com.userservice.userregistration.VO
import com.userservice.userregistration.entity.UserRegistration
data class ResponseTemplateVO(
var userRegistration: UserRegistration,
var department: Department
)
Department.kt
package com.userservice.userregistration.VO
data class Department(
val departmentId:Long=-1,
val departmentName:String="",
val departmentAddress:String="",
val departmentCode:String=""
)
UserRegistration.kt
package com.userservice.userregistration.entity
data class UserRegistration(
val userId:Long=-1,
val firstName:String="",
val lastName:String="",
val email:String="",
val departmentId:Long=-1,
)
UserRegistrationService.kt
package com.userservice.userregistration.service
import com.userservice.userregistration.VO.Department
import com.userservice.userregistration.VO.ResponseTemplateVO
import com.userservice.userregistration.entity.UserRegistration
import com.userservice.userregistration.repository.UserRegistrationRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
#Service
class UserRegistrationService {
#Autowired
private lateinit var userRegistrationRepository: UserRegistrationRepository
#Autowired
private lateinit var restTemplate: RestTemplate
fun saveUserDetails(userRegistration: UserRegistration): UserRegistration {
return userRegistrationRepository.save(userRegistration)
}
fun getUserWithDepartment(userId: Long): ResponseTemplateVO {
val vo= ResponseTemplateVO()
val userRegistration:UserRegistration=userRegistrationRepository.findUserById(userId)
val department: Department? =
restTemplate.getForObject("http://localhost:9001/departments/"+userRegistration.departmentId,
Department::class.java)
vo.userRegistration=userRegistration
if (department != null) {
vo.department=department
}
return vo
}
}
I am getting error at this below method at the line 2
val vo= ResponseTemplateVO()
No value passed for parameter department and userRegistration .This is
the error
fun getUserWithDepartment(userId: Long): ResponseTemplateVO {
val vo= ResponseTemplateVO()
val userRegistration:UserRegistration=userRegistrationRepository.findUserById(userId)
val department: Department? =
restTemplate.getForObject("http://localhost:9001/departments/"+userRegistration.departmentId,
Department::class.java)
vo.userRegistration=userRegistration
if (department != null) {
vo.department=department
}
return vo
}
This declaration:
data class ResponseTemplateVO(
var userRegistration: UserRegistration,
var department: Department
)
packs multiple things:
it declares 2 properties userRegistration and department
it defines the primary constructor of the class with 2 arguments: userRegistration and department
When you write:
val vo = ResponseTemplateVO()
You're calling the constructor of that class, but you don't specify the 2 required arguments. You should instead call it by passing the arguments:
fun getUserWithDepartment(userId: Long): ResponseTemplateVO {
val userRegistration:UserRegistration=userRegistrationRepository.findUserById(userId)
val department: Department? = restTemplate.getForObject("http://localhost:9001/departments/"+userRegistration.departmentId,
Department::class.java)
if (department == null) {
// here you should decide if it should have a default value
// or throw an exception
}
return ResponseTemplateVO(userRegistration, department)
}
Note that you declared the department property as non-null, so you need a non-null department in order to create an instance of your class.
So if department is null you have 3 options:
throw an exception
use a default value instead
change the type of department in ResponseTemplateVO so it accepts nulls (Department? with ?)
Also, if you instantiate your class with all required value like that, and you don't need to modify its properties later, the properties can be declared val. This is usually more idiomatic Kotlin. With immutability, it's easier to reason about the values.
The issue is in the data class.
data class ResponseTemplateVO(
var userRegistration: UserRegistration,
var department: Department
)
Here you have added the following params into the constructor of the data class. Hence you will need to pass the values to the constructor of the class before you can initialise it.
Hence your ResponseTemplateVO data class will become like this
data class ResponseTemplateVO(
var userRegistration: UserRegistration?=null,
var department: Department?=null)
Now since we have already assigned null as the default value. Now you can initialise the data class and it creates the data class with the values set to null and you do not need to pass any value for params to the constructor. Now you can access each of the variables and set the respective data into them.

#Query does not give desired result when native query is used

iam using spring data jpa in my project
package com.mf.acrs.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
#Data
#Entity(name= "mv_garage_asset_mapping")
public class GarageAssetMapping implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2535545189473989744L;
#Id
#Column(name="GARAGE_CODE")
private String garageCode;
#Column(name="GARAGE_NAME")
private String garageName;
#Column(name="GARAGE_ADDRESS")
private String garageAddress;
#Column(name="GARAGE_BRANCH")
private String garageBranch;
#Column(name="CONTRACT_NUMBER")
private String contractNumber;
}
this is my entity object
package com.mf.acrs.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.mf.acrs.model.GarageAssetMapping;
public interface GarageAssetMappingRepository extends JpaRepository<GarageAssetMapping, String> {
// #Query(name="select u.CONTRACT_NUMBER from mv_garage_asset_mapping u where u.GARAGE_CODE = ?1", nativeQuery = true) //**QUERY 1**
#Query("select u.contractNumber from mv_garage_asset_mapping u where u.garageCode = ?1") // **QUERY 2**
List<String> findByGarageCode(String garageCode);
}
this is my repository interface
when i use the QUERY 1 in my application the query fired by spring data jpa is
Hibernate: select garageasse0_.garage_code as garage_code1_2_, garageasse0_.contract_number as contract_number2_2_, garageasse0_.garage_address as garage_address3_2_, garageasse0_.garage_branch as garage_branch4_2_, garageasse0_.garage_name as garage_name5_2_ from mv_garage_asset_mapping garageasse0_ where garageasse0_.garage_code=?
but when i use QUERY 2 the query fired is
Hibernate: select garageasse0_.contract_number as col_0_0_ from mv_garage_asset_mapping garageasse0_ where garageasse0_.garage_code=?
QUERY 2 gives me desired result.
but my question is why spring data jpa fires a incorrect query in 1st case.
in QUERY 1 hibernate tries to pull all the data fields despite the fact i have explicitly written in query that i want to fetch only one field.
What mistake iam doing in this case?
The method defined in the controller which calls the method is below:
#PostMapping("/searchAssetsAjax")
#ResponseBody
public String searchAssetsAjax(#RequestBody SearchAssetData searchAssetData) throws IOException{
System.out.println("iam in the searchAssetsAjax "+searchAssetData);
System.out.println("iam in the searchAssetsAjax "+searchAssetData.toString());
// System.out.println("throwing exceptions" ); throw new IOException();
System.out.println("hitting the db "+searchAssetData.getGarageCode());
// List<String> contractNums = garageAssetMapRepository.findContractNumberByGarageCode(searchAssetData.getGarageCode());
List<String> contractNums = garageAssetMapRepository.findByGarageCode(searchAssetData.getGarageCode());
System.out.println("############contract num size is "+contractNums.size());
for(String contract: contractNums) {
System.out.println("contract nums are "+contract);
}
return "success";
}

Resources