DEV Community

Cover image for Cannot find symbol: class Entity — My pom.xml Said MongoDB, My Code Said MySQL
Sanjay Kumar A
Sanjay Kumar A

Posted on

Cannot find symbol: class Entity — My pom.xml Said MongoDB, My Code Said MySQL

I opened an old Spring Boot project of mine and ran a build. It failed with 20 compilation errors.

Every error said the same kind of thing: some class does not exist. @Entity does not exist. JpaRepository does not exist. My first thought was that something was wrong with my Java setup.

It wasn't. The real cause was one line in pom.xml, and it took me a while to find it.

The error

[ERROR] package org.springframework.data.jpa.repository does not exist
[ERROR] package jakarta.persistence does not exist
[ERROR] cannot find symbol: class JpaRepository
[ERROR] cannot find symbol: class Entity
[ERROR] cannot find symbol: class Table
[ERROR] cannot find symbol: class ManyToOne
[INFO] 20 errors
Enter fullscreen mode Exit fullscreen mode

The cause

@Entity, @Table and @Column come from JPA, which is for SQL databases. Those classes live in the spring-boot-starter-data-jpadependency. My project did not have it — it had spring-boot-starter-data-mongodb instead. So the compiler was right. Those classes were never in my project.

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String username;
}
Enter fullscreen mode Exit fullscreen mode

And this is what was in my pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

The fix

JPA (SQL) MongoDB
@Entity + @Table @Document
jakarta.persistence.Id org.springframework.data.annotation.Id
@GeneratedValue delete it
@Column delete it
@Column(unique = true) @Indexed(unique = true)
@ManyToOne + @JoinColumn @DBRef
JpaRepository<T, Long> MongoRepository<T, String>
Long id String id

User.java after the change:

package com.taskmanager.task_manager;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "app_users")
public class User {

    @Id
    private String id;

    @Indexed(unique = true)
    private String username;

    private String password;

    private String role = "USER";
}
Enter fullscreen mode Exit fullscreen mode

What broke next

The build went from 20 errors to 3:

[ERROR] TaskService.java:[39,45] incompatible types: java.lang.Long cannot be converted to java.lang.String
[ERROR] TaskService.java:[52,45] incompatible types: java.lang.Long cannot be converted to java.lang.String
[ERROR] TaskService.java:[59,35] incompatible types: java.lang.Long cannot be converted to java.lang.String
Enter fullscreen mode Exit fullscreen mode

MongoDB ids are String, not Long. So every method that took an id had to change:

public Task updateStatus(String id, String status, String username)
public void deleteTask(String id, String username)
Enter fullscreen mode Exit fullscreen mode

Then the controller broke too:

@PathVariable Long id      // before
@PathVariable String id    // after
Enter fullscreen mode Exit fullscreen mode

The runtime error

The build passed. The app still would not start:

Caused by: com.mongodb.DuplicateKeyException: Write failed with error code 11000
and error message 'Index build failed: E11000 duplicate key error collection:
test.users index: username dup key: { username: null }'
Enter fullscreen mode Exit fullscreen mode

Old documents in that collection had no username field, which MongoDB stores as null. A unique index cannot be built when two documents both have null.

My fix was to use fresh collections:

@Document(collection = "app_users")   // was "users"
@Document(collection = "app_tasks")   // was "tasks"
Enter fullscreen mode Exit fullscreen mode

The app started after that.

Proof it works

$r = Invoke-RestMethod -Uri http://localhost:8080/auth/login -Method Post -ContentType "application/json" -Body '{"username":"sanjay","password":"test123"}'
$h = @{ Authorization = "Bearer " + $r.token }
Invoke-RestMethod -Uri http://localhost:8080/tasks -Method Get -Headers $h
Enter fullscreen mode Exit fullscreen mode
content       : {@{description=About the MongoDB JPA mismatch;
                id=6a77526eb624bcbc15259596; status=PENDING;
                title=Write my first Dev.to article}}
totalElements : 1
totalPages    : 1
Enter fullscreen mode Exit fullscreen mode

What I would tell myself

  1. When the compiler says a Spring class does not exist, check pom.xml before checking your own code.
  2. Your config and your code must agree on the database. Mine disagreed for months because I never ran the project.
  3. Changing the id type is not a 4-file change. Search for Long id across the whole project first.
  4. E11000 ... dup key: { username: null } is about old data, not your new annotations.
  5. Always put the database name in your Mongo connection string. Without it you are writing to a database called test.
  6. A build that compiles is not a working app. Run the endpoints.

Code: github.com/sanjayfreak/Smart-Task-Manager

Top comments (0)