今天发现一个奇怪的问题:
为什么我用save保存更新的数据后,数据库不更新,但是增加了一条空数据,我的前台也把数据用json传上去了,也成功了,但是数据库没有更新相应行的数据,而是新增了一条数据,我的后端用的接口PagingAndSortingRepository,数据库hibernate+sqlserver。
前端请求代码:
request(selectedRow,'post','<%=basePath%>userManager/save',function(data){
console.log("data:"+data);
});
请求明细数据:
后端接口:
public interface UserManagerDAO extends PagingAndSortingRepository<User, Long>{
}
数据库显示:
我准备重现一下这个问题,下面的搭建过程和运行结果。
(Spring Data JPA入门案例,包含mysql、mssql增删改查、分页,主键自动生成)
1.环境准备
首先,确保你的Spring Boot项目已经配置了相关依赖。在pom.xml
中加入以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.4.1.jre8</version>
</dependency>
</dependencies>
2.应用配置
在application.properties
中配置数据库连接:
# 应用服务 WEB 访问端口
server.port=8080
# spring.datasource.url=jdbc:mysql://localhost:3306/award?useSSL=false&serverTimezone=UTC
# spring.datasource.username=root
# spring.datasource.password=123456
# spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
# spring.jpa.hibernate.ddl-auto=update
# spring.jpa.show-sql=true
spring.datasource.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=award
spring.datasource.username=sa
spring.datasource.password=A123456
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.main.lazy-initialization=true
3.实体类 (Entity)
假设我们有一个用户(User)实体,主键自增。
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String role;
@Column(name = "addtime", insertable = false, updatable = false)
private byte[] addtime;
// Getters and Setters
}
4.Repository 接口
Spring Data JPA会根据接口方法名自动生成查询语句。
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
List<User> findByUsername(String username);
Page<User> findAll(Pageable pageable);
}
5.Service 层
服务层用于业务逻辑处理。
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User save(User user) {
return userRepository.save(user);
}
public void delete(User user) {
userRepository.delete(user);
}
public User findById(Long id) {
return userRepository.findById(id).orElse(null);
}
public List<User> findByName(String name) {
return userRepository.findByUsername(name);
}
public Page<User> findAllPaged(int page, int size) {
Pageable pageable = PageRequest.of(page, size);
return userRepository.findAll(pageable);
}
public User update(Long id, User userDetails) {
return userRepository.save(userDetails);
}
public boolean deleteById(Long id) {
userRepository.deleteById(id);
return true;
}
public Page<User> findAllPaged(Pageable pageable) {
return userRepository.findAll(pageable);
}
}
6.Controller 层
控制器负责接收HTTP请求并响应。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// 创建(新增)
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User savedUser = userService.save(user);
return new ResponseEntity<>(savedUser, HttpStatus.CREATED);
}
// 查询(读取)
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
if (user != null) {
return new ResponseEntity<>(user, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
// 更新
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
User updatedUser = userService.update(id, userDetails);
if (updatedUser != null) {
return new ResponseEntity<>(updatedUser, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
// 删除
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
boolean isDeleted = userService.deleteById(id);
if (isDeleted) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
// 分页查询
@GetMapping
public ResponseEntity<Page<User>> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size);
Page<User> usersPage = userService.findAllPaged(pageable);
return new ResponseEntity<>(usersPage, HttpStatus.OK);
}
}
7.MySQL
建表语句
CREATE TABLE `users` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` VARCHAR(100) NOT NULL COMMENT '用户名',
`password` VARCHAR(100) NOT NULL COMMENT '密码',
`role` VARCHAR(100) NULL DEFAULT '管理员' COMMENT '角色',
`addtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '新增时间',
PRIMARY KEY (`id`)
) COMMENT='用户表' ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
8.MSSQL
建表语句
CREATE TABLE [dbo].[users](
[id] [int] IDENTITY(1,1) NOT NULL,
[username] [varchar](50) NOT NULL,
[password] [varchar](50) NOT NULL,
[role] [varchar](50) NULL,
[addtime] [timestamp] NULL,
CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
9.启动
成功启动
Tomcat started on port(s): 8080 (http)
Started JpademoApplication in 4.702 seconds (JVM running for 5.149)
10.新增用户
调用成功
11.查询用户
调用成功
12.修改用户
调用成功
所以,我没有重现这个问题,有可能是id传到后台的时候,丢失导致的,当所有可能都已经排除,那只剩这种可能了,网络数据丢包也会导致问题。