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
- 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.
답글 남기기