Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repository always needs an ID column #32

Closed
Bonythomasv opened this issue Jul 22, 2019 · 18 comments
Closed

Repository always needs an ID column #32

Bonythomasv opened this issue Jul 22, 2019 · 18 comments
Labels
closed: notabug The issue is not a bug

Comments

@Bonythomasv
Copy link

Bonythomasv commented Jul 22, 2019

I'm getting the following error while running a simple query with Predator JDBC and Postgress

error: Unable to implement Repository method: TaskRepository.findById(Object arg0). Cannot query entity [Task] on non-existent property: id error: Unable to implement Repository method: TaskRepository.existsById(Object arg0). Cannot query entity [Task] on non-existent property: id error: Unable to implement Repository method: TaskRepository.deleteById(Object arg0). Cannot query entity [Task] on non-existent property: id error: Unable to implement Repository method: TaskRepository.delete(Object arg0). Delete all not supported for entities with no ID error: Unable to implement Repository method: TaskRepository.delete(Object arg0). No possible implementations found.

Here is my Entity Class:
`
@entity
@DaTa
@NoArgsConstructor
//@MappedEntity(namingStrategy = NamingStrategies.Raw.class)
public class Task implements Serializable {

private static long serialVersionUID = 102843515;

@Id
@Column(name = "task_id")
@JsonProperty("task_id")
private Long taskId;

@Column(name = "assigned_workcenter")
@JsonProperty("assigned_workcenter")
@NotNull(message = "workcenter cannot be null")
private Integer assignedWorkcenter;
    ....

}`

Repositiry class:

` @JdbcRepository(dialect = Dialect.POSTGRES)
public abstract class TaskRepository implements CrudRepository<Task, Long> {

private final JdbcOperations jdbcOperations;

public TaskRepository(JdbcOperations jdbcOperations) {
    this.jdbcOperations = jdbcOperations;
}

@Transactional
public List<Task> findByTaskId(long taskId) {
    String sql = "SELECT * FROM task AS task WHERE task.task_id = ?";
    return jdbcOperations.prepareStatement(sql, statement -> {
        statement.setLong(1, taskId);
        ResultSet resultSet = statement.executeQuery();
        return jdbcOperations.entityStream(resultSet, Task.class).collect(Collectors.toList());
    });
}

} `

but if the table has the column name id then it works fine.

@graemerocher graemerocher added bug and removed bug labels Jul 23, 2019
graemerocher added a commit that referenced this issue Jul 23, 2019
@graemerocher
Copy link
Contributor

I cannot reproduce this. See 8242b56

Does your taskId property have a public getter and setter?

@Bonythomasv
Copy link
Author

Bonythomasv commented Jul 23, 2019

@graemerocher thank you for the response and you were spot on. i was using @DaTa annotation from Lombok, But when i added the Getter and Setter manually, the Repo is working. but unfortunately, with lombok @DaTa it's not working.

@JdbcRepository(dialect = Dialect.POSTGRES)
public interface  TaskRepository extends CrudRepository<Task, Long> {
}

Model:

public class Task implements Serializable {

    private static long serialVersionUID = 102843515;

    @Id
    @GeneratedValue
    private Long taskId;
    private String notes;


    public Long getTaskId() {
        return taskId;
    }

    public void setTaskId(Long taskId) {
        this.taskId = taskId;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }



}```

@schrek1
Copy link

schrek1 commented Jul 24, 2019

I have exactly same problem as described @Bonythomasv

@graemerocher
Copy link
Contributor

Most likely an interaction issue but Micronaut and Lombok. Ensure the Lombok processor is declared first

@schrek1
Copy link

schrek1 commented Jul 24, 2019

Do you mean annotation on Entity class, or order of annotation processor at the gradle file?

@graemerocher
Copy link
Contributor

In the build gradle file

@gavintranter
Copy link

I am seeing the same issue when using a Kotlin data class:

@MappedEntity("t_card")
data class Card(@Id val pan: String,
                       val activationCode: String,
                       val temporaryPassword: String,
                       val issued: Boolean = false,
                       val active: Boolean = false)

@tdudouet
Copy link

tdudouet commented Aug 9, 2019

Same here, got a Cannot query on ID with entity that has no ID error when using @MappedEntity + @Id micronaut annotations on a Kotlin class, but works well using javax.persistence.* annotations.

@graemerocher
Copy link
Contributor

@tdudouet @gavintranter I believe this is because the kotlin-jpa plugin adds special support for data classes and id by making it writable. For Micronaut Data's annotations you will need to declare the id with var instead of val for Kotlin since there is no special compiler plugin for these annotations that handle that case.

@tdudouet
Copy link

tdudouet commented Aug 9, 2019

@graemerocher Same bug moving from val to var.

@gavintranter
Copy link

@graemerocher I would love to test this but so far I am having issues with the runtime not find the repository methods, including save.

That said using the following entity the runtime does appear to build the table. I dont think it is setting the id column as an id in postgres, it would be nice if it set the uniqueness constraint, but I dont know if I would consider this an issue as such.

import javax.persistence.Entity
import javax.persistence.Id

@Entity
data class Card(@Id var pan: String,
                       val activationCode: String,
                       val temporaryPassword: String,
                       var issued: Boolean = false,
                       var active: Boolean = false)

@graemerocher
Copy link
Contributor

Do you have an example of what is not working for you?

@gavintranter
Copy link

gavintranter commented Aug 10, 2019

Sure:

@Entity
data class Card(@Id var pan: String,
                val activationCode: String,
                val temporaryPassword: String,
                var issued: Boolean = false,
                var active: Boolean = false)
@JdbcRepository(dialect = Dialect.POSTGRES)
interface CardRepository : CrudRepository<Card, String> {
    fun find(issued: Boolean): List<Card>

    fun findByIssuedFalse(): List<Card>
}
@Validated
@Controller("/card")
class CardController(private val cardRepository: CardRepository) {
    private var lastCreated: Int = -1

    @Get("/")
    fun unissuedParkingCards(): List<Card> {
        val pan = "2826%05d".format(1)
        val card = Card(pan, "ac%05d".format(1), "tp%05d".format(1))

        cardRepository.save(card)

// The find(s) produce the same exception
        val find1 = cardRepository.find(false)

        val find2 = cardRepository.findByIssuedFalse()

        return find2
    }
}

The exception is:

16:23:49.413 [pool-1-thread-5] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: All possible Introduction advise exhausted and no implementation found for method: Card save(Card entity)
io.micronaut.aop.exceptions.UnimplementedAdviceException: All possible Introduction advise exhausted and no implementation found for method: Card save(Card entity)
	at io.micronaut.aop.chain.InterceptorChain.lambda$new$0(InterceptorChain.java:86)
	at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:146)
	at io.micronaut.data.intercept.PredatorIntroductionAdvice.intercept(PredatorIntroductionAdvice.java:78)
	at io.micronaut.aop.MethodInterceptor.intercept(MethodInterceptor.java:40)
	at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:146)
	at predator.exp.CardRepository$Intercepted.save(Unknown Source)
	at predator.exp.CardController.unissuedParkingCards(CardController.kt:18)
	at predator.exp.$CardControllerDefinition$Intercepted.$$access0(Unknown Source)
	at predator.exp.$CardControllerDefinition$Intercepted$$proxy0.invokeInternal(Unknown Source)
	at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:144)
	at io.micronaut.aop.chain.InterceptorChain.lambda$new$1(InterceptorChain.java:89)
	at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:146)
	at io.micronaut.validation.ValidatingInterceptor.intercept(ValidatingInterceptor.java:122)
	at io.micronaut.aop.MethodInterceptor.intercept(MethodInterceptor.java:40)
	at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:146)
	at predator.exp.$CardControllerDefinition$Intercepted.unissuedParkingCards(Unknown Source)
	at predator.exp.$$CardControllerDefinition$InterceptedDefinition$$exec1.invokeInternal(Unknown Source)
	at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:144)
	at io.micronaut.context.DefaultBeanContext$BeanExecutionHandle.invoke(DefaultBeanContext.java:2759)
	at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:235)
	at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:122)
	at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$18(RoutingInBoundHandler.java:1388)
	at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:71)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.Flowable.subscribe(Flowable.java:14773)
	at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.Flowable.subscribe(Flowable.java:14773)
	at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.internal.operators.flowable.FlowableSwitchIfEmpty.subscribeActual(FlowableSwitchIfEmpty.java:32)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.Flowable.subscribe(Flowable.java:14773)
	at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.Flowable.subscribe(Flowable.java:14776)
	at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52)
	at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52)
	at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52)
	at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.Flowable.subscribe(Flowable.java:14773)
	at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
	at io.reactivex.Flowable.subscribe(Flowable.java:14826)
	at io.reactivex.Flowable.subscribe(Flowable.java:14773)
	at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
	at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run(ExecutorScheduler.java:288)
	at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run(ExecutorScheduler.java:253)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:835)

Just in case its useful my gradle dependencies

dependencies {
    implementation enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion")
    compileOnly enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion")
    annotationProcessor enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion")
    testAnnotationProcessor enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion")
    kapt enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion")

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}"
    implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
    implementation "io.micronaut:micronaut-runtime"
    implementation "javax.annotation:javax.annotation-api"
    implementation "io.micronaut:micronaut-http-server-netty"
    implementation "io.micronaut:micronaut-http-client"
    implementation "jakarta.persistence:jakarta.persistence-api:2.2.2"
    implementation "io.micronaut.data:micronaut-predator-jdbc:$predatorVersion"

    kapt "io.micronaut:micronaut-inject-java"
    kapt "io.micronaut:micronaut-validation"
    kapt "io.micronaut.data:micronaut-predator-processor:$predatorVersion"

    kaptTest "io.micronaut:micronaut-inject-java"

    runtimeOnly "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8"
    runtimeOnly "ch.qos.logback:logback-classic:1.2.3"
    runtimeOnly "io.micronaut.configuration:micronaut-jdbc-tomcat"
    runtimeOnly 'org.postgresql:postgresql:42.2.4'

    testImplementation "org.junit.jupiter:junit-jupiter-api"
    testImplementation "org.jetbrains.spek:spek-api:1.1.5"

    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
    testRuntimeOnly "org.jetbrains.spek:spek-junit-platform-engine:1.1.5"
}

Using
Micronaut 1.2.0.RC2
predator 1.0.0.BUILD-SNAPSHOT
kotlin 1.3.21

Thanks
Gavin

@gavintranter
Copy link

gavintranter commented Aug 10, 2019

Seems updating to Micronaut 1.2.0 and the data rather than predator versions of the 1.0.0 snapshot libs has solved my issues, I can use a natural id for my table.
Though as a key the column probably should be marked as Unique and maybe Primary Key (it at least is marked as not null), but those are things I can do at schema generation.

(As an added bonus it pulled in the fix for the bug I raised re bit/boolean field)

Thank you for your help, cant wait for this to go GA, I have been very impressed with Micronaut.

@graemerocher graemerocher added the closed: notabug The issue is not a bug label Oct 3, 2019
@noeliajimenezg
Copy link

I have exactly same problem as described @Bonythomasv on micronaut 1.2.6

@StephenOTT
Copy link

I have run into this problem with the latest released versions of micronaut with kotlin and have found that you currently need to add @field:ID, @field:AutoPopulated etc for the repository generation to work....

@macmillan78
Copy link

I am totally confused now. I have two entity data classes in my project, one with @field:Id and @field:AutoPopulated and the other one with @id and @AutoPopulated. When I remove @field: on the first one it does not compile with the error mentioned above ...

@StephenOTT
Copy link

StephenOTT commented Dec 2, 2019

I have not tested thoroughly but from my previous initial observation, some of the annotations are not being read properly at compile time of the field site target is missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed: notabug The issue is not a bug
Projects
None yet
Development

No branches or pull requests

8 participants