Spring Annotation not working in Kotlin - spring-boot

Any have problem of annotation doesnt work in Kotlin?
#Column(unique=true, nullable = false)
#Size(min = 1, max = 50)
var name: String = "",
#Size(max = 100)
var description: String = ""
I can save into database with empty string and the unique constraint also not working via the annotation. Anyone have similar issue before ? Kindly advise :)

When using Kotlin, you need to apply the constraint validators on the getter methods. This should work:
#Column(unique=true, nullable = false)
#get: Size(min = 1, max = 50)
var name: String = "",
#get: Size(max = 100)
var description: String = ""

I do not think your issue is with Kotlin exactly.
#Size and #Pattern annotation are not working in Spring MVC
It is possible that you have missed the org.hibernate:hibernate-validator package in your dependency, but without more information I cannot be certain.

You can change to
#field: Size(max = 100)
var description: String = ""

Related

#Value on R2dbc table fields

Given the following entity/table defined in a Spring/KotlinCoroutines project.
#Table("workers")
data class Worker(
#Id
val id: UUID? = null,
#Column(value = "photo")
var photo: String? = null,
// see: https://github.com/spring-projects/spring-data-r2dbc/issues/449
#Transient
#Value("#{root.photo!=null}")
val hasPhoto: Boolean = false
)
The hasPhoto field does not map to a table field. I follow the R2dbc official reference doc and use a Spring EL to evaluate the EL result as value of this field.
But when I test this hasPhoto, it always returns false even I set the photo to a nonnull string.
Got answer from the Spring guys, #Value here only can access the projection.

Hibernate Search 6 search multiple fields with multiple keywords

I want to search through these 2 different variables :
#Enumerated(EnumType.STRING)
#Column(length = 20)
#Convert(converter = WorksEnumConverter.class)
#GenericField(valueBridge = #ValueBridgeRef(type = WorksValueBridge.class))
private WorksEnum works;
#Convert(converter = AcquisitionTypeConverter.class)
#Enumerated(EnumType.STRING)
#Column(length = 10)
#GenericField(valueBridge = #ValueBridgeRef(type = AcquisitionTypeBridge.class))
private AcquisitionTypeEnum acquisitionType;
As you can see there are 2 types of Enum , and i want to use hibernate search to search via multiple keywords, I used bridge and converter and i always get the error of cannot convert string to enum
This is my code for hibernate search implementation :
if (requestSearchCustomer.getKeyword() != null) {
final String[] keywords = requestSearchCustomer.getKeyword().split(",");
final SearchPredicate keywordPredicate = getSearchScope().predicate().terms()
.fields(RequestDB_.WORKS, RequestDB_.ACQUISITION_TYPE)
.matchingAny(keywords).toPredicate();
predicate.must(keywordPredicate);
}
If you want to pass strings, and not the enum type that Hibernate Search expects, you will need to disable Hibernate Search's automatic conversion:
if (requestSearchCustomer.getKeyword() != null) {
final String[] keywords = requestSearchCustomer.getKeyword().split(",");
final SearchPredicate keywordPredicate = getSearchScope().predicate().terms()
.fields(RequestDB_.WORKS, RequestDB_.ACQUISITION_TYPE)
.matchingAny(Arrays.asList(keywords), ValueConvert.NO).toPredicate();
predicate.must(keywordPredicate);
}
See https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-dsl-argument-type

Spring's findByColumnName returning empty list

I need to retrieve a list of Category from the DB on the basis of value of column called owner. Here is my Category -
#Entity
#Table(name = "categories")
class Category(#Column(name = "category_id", nullable = false)
#Id #GeneratedValue(strategyGenerationType.AUTO)
var id: Long = 0,
#Column(name = "category_owner", nullable = false)
#field:NotNull(message = "Please assign an owner")
var owner: Long?,
#Column(name = "category_name", nullable = false)
#field:NotEmpty(message = "Please assign a name")
var name: String?)
Here is my interface which defines the function findByOwner -
interface CategoryRepository: JpaRepository<Category, Long> {
fun findByOwner(categoryOwner: Long): List<Category>
}
However, when I call the method, I get no response. I have made sure that the DB has correct data and I'm providing the correct owner Id. Have even invalidated the cache etc. What could be going wrong?
EDIT:
After spring.jpa.show-sql=true -
findAll()
Hibernate: select category0_.category_id as category1_0_, category0_.category_name as category2_0_, category0_.category_owner as category3_0_ from categories category0_
findByOwner()
Hibernate: select category0_.category_id as category1_0_, category0_.category_name as category2_0_, category0_.category_owner as category3_0_ from categories category0_ where category0_.category_owner=?
EDIT 2:
Turns out that my implementation was fine all along. The bug was in my service.
Create your named method according with the name of the column.
fun findByCategoryOwner(categoryOwner: Long): List<Category>
Or use #Query
#Query("SELECT * FROM categories WHERE category_owner = ?1", nativeQuery = true)
fun findByOwner(cateogryOwner: Long): List<Category
Can you put a breakpoint in org.springframework.data.jpa.repository.query.JpaQueryExecution class and when you execute findByOwner, it will come here.
When it reaches this breakpoint, select the query.createQuery(accessor).getResultList() and evaluate to see what value is returned by hibernate for spring-data-jpa to use
This post should help you. It appears to be happeing because of the parameter name mismatch.
Use camelCase to name your variables in Entity class then jpa will auto recognise the column name
findByCategoryOwner(String categoryOwner)
If you still wish to have underscore in your column names then try this
findByCategory_Owner(String categoryOwner)
I haven't tried the second option though
At least in java you need to provide the id in the method name:
**fun findByOwner_Id(categoryOwner: Long): List<Category>**
So change it from findByOwner -> findByOwnerId.

How to generate id field value within specific range in spring data jpa

Is there any way that I can generate ID field as 4 digit number i.e from 1000 to 9999 in my Spring boot application. Current Id field looks like this:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "EMP_ID", nullable = false)
public short getEmp_id() {
return emp_id;
}
As of now id is getting generated from 1. But I wanted to get it generated starting from 1000 and incremented by 1 until 9999.
As suggest by Ishikawa in comments and by referring Sequence Generation from Sequence Generation did below changes:
#Id
#GenericGenerator(
name = "empid-sequence-generator",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
#Parameter(name = "sequence_name", value = "user_sequence"),
#Parameter(name = "initial_value", value = "1000"),
#Parameter(name = "increment_size", value = "1")
}
)
#GeneratedValue(generator = "empid-sequence-generator")
#Column(name = "EMP_ID", nullable = false)
public short getEmp_id() {
return emp_id;
}
but even after that when trying to save the emp getting the below exception:
com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'user_sequence'.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:262)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1624)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:594)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:524)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7194)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2979)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:248)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:223)
NOTE: It's third party database so I can't do any schema/constraint changes.I need to handle this through java code only.
My bad. Forgot to uncomment below line in application.properties.
spring.jpa.hibernate.ddl-auto = update
After uncommenting when I reboot my application it created the "user_sequence".

Kotlin + Spring Boot + #Valid not worked child object's internal object

Here's the code:
data class Father(
#Valid
val sonExamResult: Son.ExamResult
)
data class Son(
val examResult:ExamResult
){
data class ExamResult(
#field: Size(min = 0, max = 100)
val math:Int,
#field: Size(min = 0, max = 100)
val physicalEducation:Int
)
}
How can I verify a data structure similar to the above? I try to pass a -1 to ExamResult.math, but nothing happend.
My native language is not English, I am very sorry for the word error.
Thank you for your help!
The #Size uses for lists and other collections, where min and max parameters restrict its size. You need to use #Max and #Min and data class
data class Father(
#field:Valid
val sonExamResult: Son.ExamResult
)
data class Son(
val examResult:ExamResult) { data class ExamResult(
#field:Min(0)
#field:Max(100)
val math:Int,
#field:Min(0)
#field:Max(100)
val physicalEducation:Int
)}
see also: kotlin and #Valid Spring annotation

Resources