🍒
SpringbootでJPAの学習中に現れたエラーを2つ紹介。
はじめに
- Springboot初学者です。
- JPAの実装の際に現れた問題についてメモ程度に残していきたいと思います。
使用技術
- Java17
- Springboot
- REST API
- JPA
- PostgreSQL
- lombok
エラーの紹介
- ERROR: null value in column "name"
- User追加をした内容は
"{\n \"name\":\"yamada\"\n}"
のようにjsonを正しく受け取れない。
開発内容について
- Userテーブルに
id
,name
カラムのみを作っています。 - ユーザー追加機能のみを実装しています。
User.java
package com.example.demo_jpa.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
}
UserRepository.java
package com.example.demo_jpa.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.demo_jpa.entity.User;
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
}
UserService.java
package com.example.demo_jpa.service;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo_jpa.entity.User;
import com.example.demo_jpa.repository.UserRepository;
import lombok.RequiredArgsConstructor;
@Service
@Transactional
@RequiredArgsConstructor
public class UserService {
private final UserRepository repository;
public User insert(String name){
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("Name cannot be null or empty");
}
User user = new User();
user.setName(name);
return repository.save(user);
}
}
UserController.java
package com.example.demo_jpa.controller;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo_jpa.entity.User;
import com.example.demo_jpa.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.PostMapping;
@RestController
@RequestMapping("")
public class UserController {
private final UserService service;
public UserController(UserService service) {
this.service = service;
}
@PostMapping("/register")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<User> register(String name) {
User saveUser = service.insert(name);
return new ResponseEntity(saveUser, HttpStatus.CREATED);
}
}
application.yml
spring:
application:
name: demo_jpa
datasource:
url: jdbc:postgresql://localhost:5432/demojpa
username: postgres
password: postgres
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update # アプリケーション起動時に、Entityに対応するテーブルがなければ作成します。
show-sql: true # 実行されるSQLをログに表示する設定。
エラー①について
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.DataIntegrityViolationException: could not execute statement [ERROR: null value in column "name" of relation "users" violates not-null constraint
詳細: Failing row contains (6, null).] [insert into users (name) values (?)]; SQL [insert into users (name) values (?)]; constraint [name" of relation "users]] with root cause
org.postgresql.util.PSQLException: ERROR: null value in column "name" of relation "users" violates not-null constraint
詳細: Failing row contains (6, null).
- エラーの原因は、
insert(name)
にnullが渡され、データベースのNOT NULL
制約に違反しているものと思われます。
解決策:アノテーション忘れ。
- UserControllerクラスの
register
メソッドの引数に@RequestParam
というアノテーションをつけ忘れていました。 - 初めはつけていたのに何かのタイミングで消していたみたいです…
- これならもっと早く気づけそうでした…
エラー②について
- ユーザーを追加したのに下記の内容で登録されてしまいました。
{
"id": 10,
"name": "{\n \"name\":\"hanako\"\n}"
}
解決策:Formクラスを作成する。
- 引数にUserFormクラスを受け取るようにしました。
UserForm.java
package com.example.demo_jpa.form;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserForm {
private String name;
}
- そのようにすると適切にUserを追加することができました。
{
"id": 12,
"name": "hanako3"
}
- 最終的なUserControllerクラスは下記の内容になりました。
UserController.java
package com.example.demo_jpa.controller;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo_jpa.entity.User;
import com.example.demo_jpa.form.UserForm;
import com.example.demo_jpa.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@RestController
@RequestMapping("")
@RequiredArgsConstructor
public class UserController {
private final UserService service;
@PostMapping("/register")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<User> register(@RequestBody UserForm form) {
User saveUser = service.insert(form.getName());
return new ResponseEntity(saveUser, HttpStatus.CREATED);
}
}
最後に
- 未熟なエラーですみません。
- まだまだいろんなことを学んでいきます。
- 新しいことを知れてよかったです!!!
Discussion