Spring Boot+JPA增删改查实例

5 篇文章 0 订阅
2 篇文章 0 订阅

本文使用spring boot配合JPA实现增删改查。并介绍orphanRemoval属性,使用该属性对子类实体进行增删操作。

阅读本文您需要掌握以下前提知识:

  • Spring Boot基础知识
  • Hibernates-JPA基础知识
  • Java基础知识

什么是orphanRemoval,百度了下发现没有非常准确且简单的定义。

orphanRemoval:当子类实体不再与父类实体关联时即删除该实体。

即,当你从父实体的相应集合中删除了该子类实体时,它会被物理删除,而非只在内存中删除。

以下为实例,模拟了评论以及点赞操作:
为了让大家更加直观,先上项目结构图:
在这里插入图片描述
AddCommentRequestBean.java : 插入评论的request bean
AddCommentLikeRequestBean.java : 点赞的request bean
CrudCommentController.java : 添删评论或点赞的接口类
CrudCommentControllerImpl.java : 添删评论或点赞的实现类
Comment.java : 评论信息实体类
CommentLike.java : 点赞信息实体类
CommentLikePK.java : 点赞信息的联合主键

本例中的父类为评论信息,子类为点赞信息,关系图如下:
在这里插入图片描述

先从实体类看起:
Comment.java
可见评论信息包含点赞信息,关系为OneToMany。并设置了orphanRemoval=true。因此将某子类实体从父类中的commentLike中移除时,其就会被物理删除。添加和移除可见本类的addCommentLike以及removeCommentLike的两个方法。用的是Set集合类的add()以及remove()方法。

package com.example.demo.entity;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.Size;

@Entity( name="Comment" )
@Table( name = "tb_comment_info" )
@NamedQuery(name = "Comment.findAll", query = "SELECT c FROM Comment c")
public class Comment {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "comment_id",columnDefinition = "BIGINT UNSIGNED")
    private Long commentId;
	
	@Size( max = 200 )
	@Column( name = "comment_body" )
	private String commentBody;
	
	@OneToMany(mappedBy = "comment", fetch = FetchType.EAGER, orphanRemoval = true, cascade = { CascadeType.PERSIST } )
	private Set<CommentLike> commentLike;

	
	public Long getCommentId() {
		return commentId;
	}

	public void setCommentId(Long commentId) {
		this.commentId = commentId;
	}

	public String getCommentBody() {
		return commentBody;
	}

	public void setCommentBody(String commentBody) {
		this.commentBody = commentBody;
	}

	public Set<CommentLike> getCommentLike() {
		return commentLike;
	}

	public void setCommentLike(Set<CommentLike> commentLike) {
		this.commentLike = commentLike;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((commentId == null) ? 0 : commentId.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Comment other = (Comment) obj;
		if (commentId == null) {
			if (other.commentId != null)
				return false;
		} else if (!commentId.equals(other.commentId))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Comment [commentId=" + commentId + ", commentBody=" + commentBody + "]";
	}

	public CommentLike addCommentLike( CommentLike commentLike ) {	
		this.getCommentLike().add( commentLike );
		commentLike.setComment( null );
		return commentLike;	
	}
	
	public CommentLike removeCommentLike( CommentLike commentLike ) {	
		this.getCommentLike().remove( commentLike );
		commentLike.setComment( null );
		return commentLike;	
	}
	
}

CommentLike.java

package com.example.demo.entity;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity( name="CommentLike" )
@Table( name = "tb_comment_like_info" )
@NamedQuery(name = "CommentLike.findAll", query = "SELECT c FROM CommentLike c")
public class CommentLike {

	@EmbeddedId
	private CommentLikePK id;

    @ManyToOne
    @JoinColumns({
    				@JoinColumn(name = "comment_id",referencedColumnName = "comment_id",insertable = false, updatable = false)
    			})
    private Comment comment;
    
	public CommentLikePK getId() {
		return id;
	}

	public void setId(CommentLikePK id) {
		this.id = id;
	}

	public Comment getComment() {
		return comment;
	}

	public void setComment(Comment comment) {
		this.comment = comment;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		CommentLike other = (CommentLike) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "CommentLike [id=" + id + "]";
	}

}

点赞实体类的联合主键
CommentLikePK.java

package com.example.demo.entity;

import java.io.Serializable;

import javax.persistence.Column;

public class CommentLikePK implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Column(name = "comment_id",columnDefinition = "BIGINT UNSIGNED")
    private Long commentId;
	
	@Column(name = "user_id",columnDefinition = "BIGINT UNSIGNED")
    private Long userId;

	public Long getCommentId() {
		return commentId;
	}

	public void setCommentId(Long commentId) {
		this.commentId = commentId;
	}

	public Long getUserId() {
		return userId;
	}

	public void setUserId(Long userId) {
		this.userId = userId;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((commentId == null) ? 0 : commentId.hashCode());
		result = prime * result + ((userId == null) ? 0 : userId.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		CommentLikePK other = (CommentLikePK) obj;
		if (commentId == null) {
			if (other.commentId != null)
				return false;
		} else if (!commentId.equals(other.commentId))
			return false;
		if (userId == null) {
			if (other.userId != null)
				return false;
		} else if (!userId.equals(other.userId))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "CommentLikePK [commentId=" + commentId + ", userId=" + userId + "]";
	}

}

再来看两个request bean
AddCommentRequestBean.java
添加评论时,评论不得为空

package com.example.demo.bean;

import javax.validation.constraints.NotBlank;
import lombok.Data;

@Data
public class AddCommentRequestBean {

	@NotBlank
	private String commentBody;
	
}

AddCommentLikeRequestBean.java
调用点赞接口时,评论编号以及用户ID不得为空。

package com.example.demo.bean;

import javax.validation.constraints.NotBlank;

import lombok.Data;

@Data
public class AddCommentLikeRequestBean {

	@NotBlank
	private Long commentId;
	
	@NotBlank
	private Long userId;
	
}

增删评论以及点赞信息的接口类

CrudCommentController.java

package com.example.demo.controller;

import javax.validation.Valid;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.bean.AddCommentLikeRequestBean;
import com.example.demo.bean.AddCommentRequestBean;

@RestController
@RequestMapping("/restapi/comment")
public interface CrudCommentController {

	@PostMapping("/add")
	public ResponseEntity<?> addComment( @Valid @RequestBody AddCommentRequestBean addCommentRequestBean );
	
	@PostMapping("/remove/{commentId}")
	public ResponseEntity<?> removeComment( @PathVariable(name="commentId", required = true ) Long commentId );
	
	@PostMapping("/like")
	public ResponseEntity<?> addCommentLike( @Valid @RequestBody AddCommentLikeRequestBean addCommentLikeRequestBean );
	
	@PostMapping("/dislike")
	public ResponseEntity<?> removeCommentLike( @Valid @RequestBody AddCommentLikeRequestBean addCommentLikeRequestBean );
	
}

增删评论以及点赞信息的实现类

CrudCommentControllerImpl.java

package com.example.demo.controllerimpl;

import javax.transaction.Transactional;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import com.example.demo.bean.AddCommentLikeRequestBean;
import com.example.demo.bean.AddCommentRequestBean;
import com.example.demo.controller.CrudCommentController;
import com.example.demo.entity.Comment;
import com.example.demo.entity.CommentLike;
import com.example.demo.entity.CommentLikePK;
import com.example.demo.repository.CommentRepository;

@Component
@Transactional
public class CrudCommentControllerImpl implements CrudCommentController {

	@Autowired
	private CommentRepository commentRepository;
	
	@Override
	public ResponseEntity<?> addComment(@Valid AddCommentRequestBean addCommentRequestBean) {
		// TODO Auto-generated method stub
		
		// 生成新的评论
		Comment comment = new Comment();
		// 设置评论内容
		comment.setCommentBody( addCommentRequestBean.getCommentBody() );
		// 使用仓库存储
		commentRepository.save( comment );
		
		return new ResponseEntity<>("成功添加评论",HttpStatus.OK);
	}

	@Override
	public ResponseEntity<?> removeComment( Long commentId ) {
		// TODO Auto-generated method stub
		
		// 使用仓库根据评论ID删除评论
		commentRepository.deleteById( commentId );
		
		return new ResponseEntity<>("成功删除评论",HttpStatus.OK);
	}

	@Override
	public ResponseEntity<?> addCommentLike(@Valid AddCommentLikeRequestBean addCommentLikeRequestBean) {
		// TODO Auto-generated method stub
		
		// 如果评论不存在则报错,存在则获取该实体
		Comment comment = commentRepository.findById( addCommentLikeRequestBean.getCommentId() )
				                           .orElseThrow(()-> new RuntimeException("该评论不存在"));
		
		// 生成点赞信息的联合主键
		CommentLikePK commentPK = new CommentLikePK();
		commentPK.setCommentId( addCommentLikeRequestBean.getCommentId() );
		commentPK.setUserId( addCommentLikeRequestBean.getUserId() );
		
		// 生成点赞信息,并设置主键
		CommentLike commentLike = new CommentLike();
		commentLike.setId( commentPK );
		
		// 当子类实体中没有该用户的点赞信息时插入
		// 注意equals和hashCode是否正确,如不正确contains执行结果会错误
		if( !comment.getCommentLike().contains( commentLike ) ) {
			comment.addCommentLike( commentLike );
		}
		
		return new ResponseEntity<>("成功点赞",HttpStatus.OK);
	}

	@Override
	public ResponseEntity<?> removeCommentLike(@Valid AddCommentLikeRequestBean addCommentLikeRequestBean) {
		// TODO Auto-generated method stub

		Comment comment = commentRepository.findById( addCommentLikeRequestBean.getCommentId() )
                						   .orElseThrow(()-> new RuntimeException("该评论不存在"));
		
		// 生成点赞信息的联合主键
		CommentLikePK commentPK = new CommentLikePK();
		commentPK.setCommentId( addCommentLikeRequestBean.getCommentId() );
		commentPK.setUserId( addCommentLikeRequestBean.getUserId() );
		
		CommentLike commentLike = new CommentLike();
		commentLike.setId( commentPK );
		
		// 当子类实体中有当前用户的点赞信息时删除该点赞信息
		// 注意equals和hashCode是否正确,如不正确contains执行结果会错误
		if( comment.getCommentLike().contains( commentLike ) ) {
			comment.removeCommentLike( commentLike );
			return new ResponseEntity<>("成功取消点赞",HttpStatus.OK);
			
		}else {
			// do nothing
			return new ResponseEntity<>("已取消点赞",HttpStatus.OK);
		}
	}

}

YML文件

server:
  port: 8083
  tomcat:
    uri-encoding: UTF-8
spring: 
  application: 
    name: demo
  mvc: 
    static-path-pattern: static/**
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    #本例使用mysql,如使用其他DB请自行切换
    url: jdbc:mysql://localhost/test_database?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
    #注意此处切换为自己的账号密码
    username: 
    password: 
  jpa:
    #为当前线程配置EntityManager
    open-in-view: false
    #自动执行DDL
    generate-ddl: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect
        ddl-auto: update

POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
		<dependency>
		    <groupId>javax.validation</groupId>
		    <artifactId>validation-api</artifactId>
		    <version>2.0.1.Final</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

使用PostMan测试

起始状态,两个表皆为空
在这里插入图片描述

调用CrudCommentController的addComment()方法添加评论
在这里插入图片描述
确认评论数据是否被添加
在这里插入图片描述

再调用CrudCommentController的addCommentLike()方法为该评论添加点赞信息。
在这里插入图片描述
再次查看点赞表数据,点赞信息被添加。
在这里插入图片描述

再调用CrudCommentController的removeCommentLike()方法移除该点赞信息。

在这里插入图片描述

最后调用CrudCommentController的removeComment()来移除刚刚添加的评论。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是关于如何使用Spring Boot实现增删改查实例的建议: 1. 首先,您需要创建一个Spring Boot项目,并将所需的依赖项添加到您的项目中。例如,您可能需要添加Spring Data JPASpring Web、MySQL或其他相关依赖项。 2. 接下来,您需要定义实体类。实体类应该与您的数据库表相对应,并包含与表列对应的属性和相应的getter和setter方法。 3. 然后,您需要创建一个JpaRepository接口来管理您的实体类。JpaRepository提供了许多标准的CRUD方法,如save()、delete()、findAll()等。 4. 在您的应用程序中,您需要创建一个控制器类来处理HTTP请求,并将其映射到适当的JpaRepository方法。例如,您可以使用@GetMapping注释将HTTP GET请求映射到findAll()方法。 5. 最后,您需要配置您的数据库连接。在application.properties文件中,您可以指定数据库URL、用户名和密码等信息。您还可以配置Hibernate方言、DDL自动创建和更新策略等。 下面是一个简单的示例,它演示了如何使用Spring Boot进行基本的增删改查操作: ```java @RestController @RequestMapping("/api") public class UserController { @Autowired private UserRepository userRepository; @GetMapping("/users") public List<User> getAllUsers() { return userRepository.findAll(); } @PostMapping("/users") public User createUser(@RequestBody User user) { return userRepository.save(user); } @GetMapping("/users/{id}") public User getUserById(@PathVariable Long id) { return userRepository.findById(id) .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id)); } @PutMapping("/users/{id}") public User updateUser(@PathVariable Long id, @RequestBody User userToUpdate) { return userRepository.findById(id) .map(user -> { user.setName(userToUpdate.getName()); user.setEmail(userToUpdate.getEmail()); return userRepository.save(user); }) .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id)); } @DeleteMapping("/users/{id}") public ResponseEntity<?> deleteUser(@PathVariable Long id) { return userRepository.findById(id) .map(user -> { userRepository.delete(user); return ResponseEntity.ok().build(); }) .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id)); } } ``` 在这个示例中,UserController类处理了所有用户相关的HTTP请求,并将它们映射到适当的JpaRepository方法。例如,getAllUsers()方法将HTTP GET请求映射到findAll()方法,createUser()方法将HTTP POST请求映射到save()方法,以此类推。 希望这能够帮助您实现您的增删改查实例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值