我正在 Spring Boot 中开发一个简单的博客后端作为个人项目。我这样做是为了尝试学习一些 Java Spring,但我在使用下面的代码时遇到了问题(有很多......)。
我得到的错误正是这样的:在 null 中定义的 bean 'postRepository' 无法注册。具有该名称的 bean 已在 null 中定义,并且覆盖已禁用。
当我使用 Hibernate 时,代码本身工作得很好,我有 2 个 DAO、2 个 DAOImpl,并使用服务类中的这些来调用数据库并返回。一切都按预期进行 - 可以返回完整的用户列表,可以返回完整的帖子列表,单个用户/帖子等。所有 CRUD 操作。
如果我理解正确的话,要切换到 Spring Data JPA,我所需要做的就是摆脱 DAO
和DAOImplementations
每个实体只有一个扩展 JpaRepository<T, T>
的接口(interface)它将提供 findById、findAll、save、delete 等的实现。但是,进行更改后,删除 DAO
和DAOImplementations
然后更新 ServiceImplementations,我收到上述错误。以下是实体类:
课后:
package com.me.website.entity;
@Entity
@Table(name="posts")
public class Post {
//fields of the Post object
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="title")
private String title;
@Column(name="author")
private String author;
@Column(name="date")
private LocalDateTime date;
@Column(name="excerpt")
private String excerpt;
@Column(name="featured_media")
private byte[] featuredMedia;
@Column(name="content")
private String content;
@Column(name="category")
private String category;
//constructor for the Post object
public Post(String title, String author, LocalDateTime date, String excerpt, byte[] featuredMedia, String content, String category) {
this.title = title;
this.author = author;
this.date = date;
this.excerpt = excerpt;
this.featuredMedia = featuredMedia;
this.content = content;
this.category = category;
}
public Post() {}
@Override
public String toString() {
return "Post{" +
"id=" + id +
", title='" + title + '\'' +
", author=" + author +
", date=" + date +
", excerpt='" + excerpt + '\'' +
", featuredMedia=" + Arrays.toString(featuredMedia) +
", content='" + content + '\'' +
", category='" + category + '\'' +
'}';
}
//getters and setters
用户类别
package com.me.website.entity;
@Entity
@Table(name="users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Integer id;
@Column(name="username")
private String username;
@Column(name="display_name")
private String displayName;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="email")
private String email;
@Column(name="password")
private String password;
public User() {}
public User(String username, String displayName, String firstName, String lastName, String email, String password) {
this.username = username;
this.displayName = displayName;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", displayName='" + displayName + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
'}';
}
//getters and setters
使用 Spring Data JPA 的 DAO
package com.me.website.dao;
public interface PostRepository extends JpaRepository<Post, Integer> {
//no implementation required
}
package com.psyonik.website.dao;
public interface UserRepository extends JpaRepository<User, Integer> {
//no implementation required
}
帖子/用户服务
package com.me.website.service;
public interface PostService {
public List<Post> findAll();
public Post findById(int theId);
public void save(Post thePost);
public void deleteById(int theId);
}
package com.me.website.service;
public interface UserService {
public List<User> findAll();
public User findById(int theId);
public void save(User theUser);
public void deleteById(int theId);
}
服务实现
package com.me.website.service;
@Service
public class PostServiceImpl implements PostService {
private PostRepository postRepository;
@Autowired
public PostServiceImpl(PostRepository thePostRepository) {
postRepository=thePostRepository;
}
@Override
public List<Post> findAll() {
return postRepository.findAll();
}
@Override
public Post findById(int theId) {
Post thePost = null;
Optional<Post> byId = postRepository.findById(theId);
if (byId.isPresent()) {
thePost = byId.get();
}
return thePost;
}
@Override
public void save(Post thePost) {
postRepository.save(thePost);
}
@Override
public void deleteById(int theId) {
postRepository.deleteById(theId);
}
}
package com.me.website.service;
@Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public List<User> findAll() {
return userRepository.findAll();
}
@Override
public User findById(int theId) {
User theUser = null;
Optional<User> thisUser = userRepository.findById(theId);
if (thisUser.isPresent()) {
theUser = thisUser.get();
}
return theUser;
}
@Override
public void save(User theUser) {
userRepository.save(theUser);
}
@Override
public void deleteById(int theId) {
userRepository.deleteById(theId);
}
}
POST 休息 Controller
package com.me.website.restcontroller;
@RestController
@RequestMapping("/")
public class PostRESTController {
private PostService postService;
@Autowired
public PostRESTController(PostService thePostService) {
postService = thePostService;
}
/*GET mapping - this one returns a list of all the posts =========================================================*/
@GetMapping("/blog")
public List<Post> findAll() {
return postService.findAll();
}
/*GET mapping - this provides a pathvariable for a postId to retrieve a particular post item or return an error ==*/
@GetMapping("/blog/{postId}")
public Post findById(@PathVariable int postId) {
Post post = postService.findById(postId);
if (post == null) {
throw new RuntimeException("Post not found " + postId);
}
else return post;
}
/*POST mapping - this creates a new blogpost object and saving it to the db ======================================*/
@PostMapping("/blog")
public Post addPost(@RequestBody Post thePost) {
//in case an id is passed, this will be converted to 0 to force an insert instead of an update
thePost.setId(0);
postService.save(thePost);
return thePost;
}
/*PUT mapping - this updates a given blog post given the id passed through =======================================*/
@PutMapping("/blog")
public Post updatePost(@RequestBody Post thePost) {
postService.savePost(thePost);
return thePost;
}
/*DELETE mapping - this is to delete a specific blog post item ===================================================*/
@DeleteMapping("/blog/{blogId}")
public String deletePost(@PathVariable int blogId) {
//retrieve the correct post
Post thePost = postService.findById(blogId);
//throw exception if null
if (thePost == null) {
throw new RuntimeException("This post doesn't exist in db. Post ID: " + blogId);
}
else {
postService.deleteById(blogId);
}
return "Deleted post with id: " + blogId;
}
}
package com.me.website;
@SpringBootApplication
public class WebsiteApplication {
public static void main(String[] args) {
SpringApplication.run(WebsiteApplication.class, args);
}
}
我已经删除了导入语句,因为一切看起来都很好......
我只是不明白为什么会发生这种情况。我在想,也许 spring bean 工厂正在尝试制作多个后存储库 bean,但没有理由这样做......
我想也许我只是错过了配置(但事实并非如此,因为 Spring Boot 项目的主要方法有 @SpringBootApplication
,它负责所有这些)。
然后我想我需要添加 @Transactional
关于JpaRepository
接口(interface),但如果我从 Spring Boot Data 文档中正确理解了这一点,情况就不是这样了……我需要为两个 JpaRepository 接口(interface)设置 bean 名称属性吗?
如果是这样,为什么? :) 构造函数不会使用不同的类名称(PostRepository 与 UserRepository)吗?
最佳答案
这两个建议都没有帮助,正如我之前提到的和现在研究的 Spring boot 一样,您实际上并不需要 @Repository
或使用 @EnableJpaRepositories("package.name")
因为 @SpringBootApplication
会为您完成所有扫描,只要您的存储库位于同一个包中。如果一个实体的一个包中有一个存储库,另一个实体和另一个存储库的另一个包中有一个存储库,则需要使用此限定符来确保正确扫描包。
该修复实际上完全不直观 - 我的 pom.xml 仍然引用了导致问题的 spring-boot-starter-data-jdbc
。注释掉之后,这个问题就解决了。
对于任何希望能够看到第一个版本与编辑版本之间的差异的人,您可以查看我的github here 。数据库是 MySQL,它有 2 个表,一张称为 post,一张称为本地运行的 user。希望它对将来的人有所帮助:) 谢谢您的回答。
关于java - 无法注册以 null 定义的 bean 'postRepository' 。具有该名称的 bean 已在 null 中定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58557334/