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
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;
}
And this is what was in my pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
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";
}
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
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)
Then the controller broke too:
@PathVariable Long id // before
@PathVariable String id // after
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 }'
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"
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
content : {@{description=About the MongoDB JPA mismatch;
id=6a77526eb624bcbc15259596; status=PENDING;
title=Write my first Dev.to article}}
totalElements : 1
totalPages : 1
What I would tell myself
- When the compiler says a Spring class does not exist, check
pom.xmlbefore checking your own code. - Your config and your code must agree on the database. Mine disagreed for months because I never ran the project.
- Changing the id type is not a 4-file change. Search for
Long idacross the whole project first. -
E11000 ... dup key: { username: null }is about old data, not your new annotations. - Always put the database name in your Mongo connection string. Without it you are writing to a database called
test. - A build that compiles is not a working app. Run the endpoints.
Top comments (0)