java - JPA:主键的重复条目

标签 java mysql hibernate jpa eclipselink

过去 4 个小时我一直在处理这个 JPA 问题。最后我放弃了,所以我向你寻求帮助。到目前为止,我几乎尝试了所有建议的解决方案。

我试过了,

1) 映射变化(@ManyToOne, @OneToOne, @OneToMany)

2) 级联选项(PERSIST、MERGE、ALL..)

3) 禁用缓存

3) 许多其他不具体的尝试,如 1,2 和 3。只是为了希望。 :)

测试类

public class testClass {
public static void main(String[] args) {

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("CSE_482_Project_4_-_PersistencePU");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();

    File parentFile = new File("cleardata");
    File[] allFiles = parentFile.listFiles();
    File myFile;
    int k = 1;

    for(int f =0; f<allFiles.length; f++){
    try {
        myFile=allFiles[f];
        BufferedReader br = new BufferedReader(new FileReader(myFile));

        String tempDate = br.readLine();
        tempDate = tempDate.substring(17);
        String[] tempDateArr = tempDate.split(" ");
        int day = Integer.parseInt(tempDateArr[0]);
        int month = Integer.parseInt(tempDateArr[1]);
        int year = Integer.parseInt(tempDateArr[2]);

        Date leavingDate = new Date(year, month, day);

        String studentNumber = br.readLine().substring(13);
        boolean minor = true;
        if (br.readLine().contains("false")) {
            minor = false;
        }
        Student stu = new Student(studentNumber, leavingDate);
        stu.setMinorDegree(minor);

        tx.begin();
        em.persist(stu);
        tx.commit();

        String currentLine;
        Slot s;
        Course c;
        SlotAndCourse sc;
        int semester = 0;
        String courseCode = "";
        String slotName = "";
        int credit = 0;
        String termTaken = "";
        int yearTaken = 0;
        String grade = "";
        boolean semesterSet = false;
        boolean courseSet = false;
        boolean gradesSet = false;

        int count = 0;


        while ((currentLine = br.readLine()) != null) {
            String[] arr = currentLine.split(" ");

            if (arr[0].equals("semester")) {
                semester = Integer.parseInt(arr[1]);
                semesterSet = true;
            } else if (arr[0].matches("^([0-9]+[a-zA-Z]+|[a-zA-Z]+[0-9]+)[0-9a-zA-Z]*$")) { // contains both latters and digits CS112
                courseCode = arr[0];
                slotName = arr[1];
                credit = Integer.parseInt(arr[2]);
                courseSet = true;
            } else if (arr[0].equals("numberofattempts")) {
                int n = Integer.parseInt(arr[1]);
                for (int i = 0; i < n; i++) {
                    currentLine = br.readLine();
                    System.out.println(currentLine);
                    arr = currentLine.split(" ");
                    yearTaken = Integer.parseInt(arr[0]);
                    termTaken = arr[1];
                    grade = arr[2];
                }
                gradesSet = true;
            }

            if (gradesSet && courseSet && semesterSet) {
                s = new Slot();
                c = new Course(courseCode);

                s.setCredit(credit);
                s.setSemester(semester);
                s.setSlotName(slotName);
                s.setSlotCode("" + k);

                c.setCourseCode(courseCode);

                sc = new SlotAndCourse(s,c,yearTaken,termTaken);
                sc.setCourse(c);
                sc.setSlot(s);
                sc.setGrade(grade);

                tx.begin();

                em.clear();    // just a try, but didn't work
                em.persist(sc);
                tx.commit();                 

                courseSet = false;
                semesterSet = false;
                gradesSet = false;
                k++;
            }

        }

    } catch (Exception ex) {
        System.out.println(ex.toString());
        ex.printStackTrace();
    }
    }
     em.close();
}

}

学生类(class)

@Entity
@Cacheable(false)
public class Student implements Serializable {

@Id
private String studentNumber;

@Temporal(TemporalType.DATE)
private Date leavIngDate;
private boolean mInorDegree;

public Student() {
}

public Student(String studentNumber, Date leavingDate) {
    this.studentNumber = studentNumber;
    this.leavIngDate = leavingDate;
}

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Slot)) {
        return false;
    }
    Student other = (Student) obj;
    if ((this.studentNumber == null &&  other.studentNumber != null) || (this.studentNumber != null && !this.studentNumber.equals(other.studentNumber))) {
        return false;
    }
    return true;
}

@Override
public int hashCode() {
   int hash = 0;
    hash += (studentNumber != null ? studentNumber.hashCode() : 0);
    return hash;
}

  // setters and getters

类(class)类(class)

  @Entity
  @Cacheable(false)
  public class Course implements Serializable {

  @Id
  private String courseCode;

public Course() {
}

public Course(String courseCode) {
    this.courseCode = courseCode;
}

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Course)) {
        return false;
    }
    Course other = (Course) obj;
    if ((this.courseCode == null && other.courseCode != null) || (this.courseCode != null && !this.courseCode.equals(other.courseCode))) {
        return false;
    }
    return true;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (courseCode != null ? courseCode.hashCode() : 0);
    return hash;
}

  //setters and getters

插槽类

  @Entity
  @Cacheable(false)
  public class Slot implements Serializable {
  @Id
private String slotCode;
private String slotName;
private int credIt;
private int semester;

public Slot() {
}

public Slot(String slotCode, String slotName) {
    this.slotCode = slotCode;
    this.slotName = slotName;
}

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Slot)) {
        return false;
    }
    Slot other = (Slot) obj;
    if ((this.slotCode == null && other.slotCode != null) || (this.slotCode != null && !this.slotCode.equals(other.slotCode))) {
        return false;
    }
    return true;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (slotCode != null ? slotCode.hashCode() : 0);
    return hash;

     //setters getters

SlotAndCourse 类

@Entity
@Cacheable(false)
public class SlotAndCourse implements Serializable {
@EmbeddedId
protected SlotAndCoursePK slotAndCoursePK;

@JoinColumn(name = "SLOTCODE", referencedColumnName = "SLOTCODE", insertable = false, updatable = false)
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.ALL})
private Slot slot;

@JoinColumn(name = "COURSECODE", referencedColumnName = "COURSECODE", insertable = false, updatable = false)
@ManyToOne(cascade = CascadeType.PERSIST)
private Course course;

private String grade;

public SlotAndCourse() {
}

public SlotAndCourse(SlotAndCoursePK slotAndCoursePK) {
    this.slotAndCoursePK = slotAndCoursePK;
}

public SlotAndCourse(String slotCode, String courseCode, int yearTaken, String termTaken) {
    this.slotAndCoursePK = new SlotAndCoursePK(slotCode, courseCode, yearTaken, termTaken);
}
public SlotAndCourse(Slot s, Course c, int yearTaken, String termTaken) {
    this.slot = s;
    this.course = c;
    this.slotAndCoursePK = new SlotAndCoursePK(s.getSlotCode(), c.getCourseCode(),yearTaken,termTaken);
}

@Override
public boolean equals(Object obj) {
   if(obj instanceof SlotAndCourse){
        SlotAndCourse arg = (SlotAndCourse)obj;
        return this.slotAndCoursePK.equals(arg.slotAndCoursePK);
    }
    else if(obj instanceof SlotAndCoursePK){
        SlotAndCoursePK arg = (SlotAndCoursePK)obj;
        return this.slotAndCoursePK.equals(arg);
    }
    return false;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (slotAndCoursePK != null ? slotAndCoursePK.hashCode() : 0);
    return hash;
}

SlontAndCoursePK 类

 @Embeddable
 public class SlotAndCoursePK implements Serializable{

protected String slotCode;
protected String courseCode;
protected int yearTaken;
protected String termTaken;

public SlotAndCoursePK() {
}

public SlotAndCoursePK(String slotCode, String courseCode, int yearTaken, String termTaken) {
    this.slotCode = slotCode;
    this.courseCode = courseCode;
    this.yearTaken = yearTaken;
    this.termTaken = termTaken;
}

 @Override
public int hashCode() {
    int hash = 0;
    hash += (slotCode != null ? slotCode.hashCode() : 0);
    hash += (courseCode != null ? courseCode.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof SlotAndCoursePK)) {
        return false;
    }
    SlotAndCoursePK other = (SlotAndCoursePK) object;
    if ((this.slotCode == null && other.slotCode != null) || (this.slotCode != null && !this.slotCode.equals(other.slotCode))) {
        return false;
    }
    if ((this.courseCode == null && other.courseCode != null) || (this.courseCode != null && !this.courseCode.equals(other.courseCode))) {
        return false;
    }
    return true;
}

 // setters and getters

我为在这里复制和粘贴所有代码感到非常难过。我希望有人可以帮助我了解我所缺少的东西。 testClass 的第一部分是从现有的结构良好的文本文件中读取并填充相关数据字段。

当我运行调试时会发生什么; 首先一切顺利,它按预期将学生、类(class)、slotAndCourses 添加到 db,但是当创建一个在 db 中具有现有 courseCode 的 slotAndCourse 实例并尝试将其持久化(不确定它是否正确)到数据库时,它给我重复类(class)表中的主键条目。

错误看起来像这样:

javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'cse110' for key 'PRIMARY' Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'cse110' for key 'PRIMARY' Error Code: 1062 Error Code: 1062 Call: INSERT INTO COURSE (COURSECODE) VALUES (?) Call: INSERT INTO COURSE (COURSECODE) VALUES (?)

最佳答案

我的猜测是 cleardata 是一个包含文本文件的目录。 cleardata 目录中的每个文件都包含单个学生的数据。

我想很多学生都可以参加一门类(class),所以您不应该每次在文本文件中找到它时都创建一门类(class)。

而不是 c = new Course(courseCode); 您应该搜索数据库以查看是否有类(class)的保存版本。类似的事情可能会有所帮助(我没有测试这段代码):

public Course findOrCreateCourse(String courseCode) {
    Course course = em.find(Course.class, courseCode);
    if (course == null)
        course = new Course(courseCode);
    }
    return course;
}

您可能对其他实体有同样的问题。

关于java - JPA:主键的重复条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30016470/

相关文章:

java - JPA CriteriaQuery - 如何使用 IN 比较运算符

java - 为什么我收到此错误文件过早结束?

MySQL 挑选出多行

java - Android 谷歌地图 v2 不显示指南针和位置图标

mysql - 比较 mysql 中的 double 值似乎无法正常工作

php - 帮助逻辑

java - Hibernate 生成带有 JPA @Enumerated 注释的 VARBINARY 列

java - Hibernate QueryException : Expected positional parameter count, 但查询不带参数

java - 如何在 HiveMQ 客户端(MQTT)中获取客户端的名称?

java - 共享和存储 RSA - Java 服务器中的公钥,反之亦然