通过Postgres获取“重复键值违反唯一约束”

时间:2019-12-15 08:22:54

标签: java spring postgresql spring-boot jpa

我正在使用Springboot应用程序。


问题陈述:
我正在使用序列生成ID。 当我第一次接触控制器时,也没有例外,并且数据已成功保存到数据库中。
但是当我第二次碰到控制器时,我得到了:

**duplicate key violates unique constraint, Detail: 
Key(id)=(100) already exits.** <br/>

但是id = 100早已插入10条记录。

我在POJO以下:

package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "student_tbl", schema = "user")
public class Student {

@Id
private Integer id;
private String name;
private String className;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getClassName() {
    return className;
}

public void setClassName(String className) {
    this.className = className;
}

public Integer getId() {
    return id;
}

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

}

学生资料库

package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface StudentRepository extends JpaRepository<Student, Integer> {

@Query(value = "select nextval('user.student_id')", nativeQuery = true)
Integer createId();

}

PersistStudent

package com.example.demo;

import java.util.List;
import java.util.stream.IntStream;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersistStudent {

@Autowired
private StudentRepository studentRepository;

@PersistenceContext
EntityManager entityManager;

@Transactional
public void persistStudent(List<Student> students) {

    try {

        IntStream.range(0, students.size()).forEach(index -> {
            if (students.size() == index || index % 100 == 0) {
                entityManager.flush();
                entityManager.clear();
            }

            entityManager.persist(students.get(index));
        });
    } catch (Exception e) {
        System.out.println("Exception:: " + e);
    }
}

}

控制器

package com.example.demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StudentContoller {

@Autowired
private PersistStudent persistStudent;

@Autowired
private StudentRepository studentRepo;

@GetMapping(value = "/save")
public void saveStudent() {

    List<Student> students = new ArrayList<Student>();
    Student stu = new Student();
    stu.setClassName("VII");
    stu.setName("John Doe");
    stu.setId(studentRepo.createId());

    students.add(stu);

    persistStudent.persistStudent(students);
}

}

请帮助。

2 个答案:

答案 0 :(得分:0)

您只需使用@Generated注释Student.id字段,就可以避免管理实体id的全部开销。这样,您可以简单地将id字段留为空白,并在插入时为实体分配一个唯一的ID。我还建议使用JpaRepository中的方法进行创建/读取/更新/删除操作。

代码将变为:

@Entity
@Table(name = "student_tbl", schema = "user")
public class Student {

@Id
@Generated
private Integer id;
private String name;
private String className;

....

@Service
public class PersistStudent {

@Autowired
private StudentRepository studentRepository;

@Transactional
public void persistStudent(List<Student> students) {
    studentRepository.saveAll(students);
}
}

....

@RestController
public class StudentContoller {

@Autowired
private PersistStudent persistStudent;

@GetMapping(value = "/save")
public void saveStudent() {

    List<Student> students = new ArrayList<Student>();
    Student stu = new Student();
    stu.setClassName("VII");
    stu.setName("John Doe");
    students.add(stu);

    persistStudent.persistStudent(students);
}

}

答案 1 :(得分:0)

希望您的序列工作正常,那么您无需致电stu.setId(studentRepo.createId());

只需在您的id字段中添加以下注释:

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "user_id")
  private int id;