I've encountered a problem where Spring doesn't see new @Column names of @Entity
Exact example which I run:
package pckg;
import javax.persistence.*;
@Entity
@Table(name = "example")
class Example {
@Column(name = "id")
public int id;
@Column(name = "old")
public int old;
}
package repo;
import org.springframework.data.jpa.repository.JpaRepository;
import pckg.Example;
public interface ExampleRepository extends JpaRepository<Example, Int> {
Example findById(long id);
}
Rest code is Scala, which, I hope, is fine enough to read
package controller;
import repo.ExampleRepository
import pckg.Example
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.{Page, PageRequest, Sort}
import org.springframework.web.bind.annotation.{GetMapping, RequestParam, RestController}
class ExampleController {
@Autowired
private var repo: ExampleRepository = _
@GetMapping(value = Array("/example"))
def getPage(@RequestParam(value = "page", defaultValue = "0") page: String,
@RequestParam(value = "size", defaultValue = "10") size: String,
@RequestParam(value = "sort", defaultValue = "id") sortBy: String) Array[Example] = try {
val pageNumber = page.toInt
val requestedSize = size.toInt
val sort = Sort.by(sortBy)
val pageable = PageRequest.of(pageNumber, requestedSize, sort)
val resultPage: Page[Example] = repo.findAll(pageable)
resultPage.getContent.asScala.toArray
} catch {
case e: Throwable => Array.empty
}
}
import org.springframework.boot.{CommandLineRunner, SpringApplication}
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class App {}
object App {
def main(args: Array[String]): Unit = {
SpringApplication.run(classOf[App], args: _*)
}
}
application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/example
spring.datasource.username=example
spring.datasource.password=example
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
I build and run this code, testing with browser, making requests on localhost:8080/example endpoint with parameter sort="old" like this: localhost:8080/example?sort=old
And then I change @Column name from "old" to "bnew" like this:
package pckg;
import javax.persistence.*;
@Entity
@Table(name = "example)
class Example {
@Column(name = "id")
public int id;
// @Column(name = "old")
@Column(name = "bold")
public int old;
}
Fully rebuild project, run app, hibernate logs seems fine as they show that old table was dropped, new table created, fields are named correctly but... Using localhost:8080/example?sort=bold leads to
org.springframework.data.mapping.PropertyReferenceException: No property 'bold' found for type 'Example'! Did you mean ''old''?
If you have an idea what's going on or at least have a tip where the issue comes from I would gladly listen and dive in answer
UPD
After renaming field "old" to "bold" I found out that there is a problem with naming strategy, so I considered defining
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
in my application.properties, hoping it would help, but it didn't
Is there any way?
UPD 2 Warning: in order to achieve results I achieved while debugging you need Hibernate 5.6.9, Spring 2.7.0, blank started app (you haven't made any requests involving your test-request yet, so there is nothing in request cache (except for id field)) .......... In short, you can directly jump to PropertyPath(String name, TypeInformation<?> owningType, List base), which is a constructor for PropertyPath class, executing logic of our program, in which we will fall in CachedIntrospectionResults::getPropertyDescriptor(String name) which checks that descriptor of our class has a corresponding field (this field's name equals to the sortBy parameter in our case), and, if field's name not same as sortBy parameter, we will not get our sorting or get it wrong (since it's another, not mentioned by us field)
Thus question is closed, no hope here
CodePudding user response:
package pckg;
import javax.persistence.*;
@Entity
@Table(name = "example)
class Example {
@Column(name = "id")
public int id;
// @Column(name = "old")
@Column(name = "bold")
public int old;
}
You missed a colon "
in the @Table(name = "example)
.
CodePudding user response:
Answer is actual for Hibernate 5.6.9, didn't check what's going on in another versions.
Let us debug while executing our page request (repo.findAll(pageable))
Skipping all wrapper, calls and checks: in short, you can directly jump to PropertyPath(String name, TypeInformation<?> owningType, List base), which is a constructor for PropertyPath class, executing logic of our program, in which we will fall in CachedIntrospectionResults::getPropertyDescriptor(String name) which checks that descriptor of our class has a corresponding field (this field's name equals to the sortBy parameter in our case), and, if field's name not same as sortBy parameter, we will not get our sorting or get it wrong (since it's another, not mentioned by us field)
Thus question is closed, no hope here