两个难搞的Java Error/Exception

编程入门 行业动态 更新时间:2024-10-20 17:30:43

<a href=https://www.elefans.com/category/jswz/34/1771443.html style=两个难搞的Java Error/Exception"/>

两个难搞的Java Error/Exception

最近维护公司的产品时,我碰到了两个头痛的Java异常。未免以后忘记了,所以写篇blog记录下这些问题和解决方法。

由于不能展示公司的代码,我就用书店、书、作者这些对象来说明。书店与作者之间是m:n的关系,作者与书之间是1:n的关系。各个对象定义如下:

import jakarta.persistence.*;
import java.io.Serializable;
import java.util.*;
import org.hibernate.annotations.*;
import org.hibernate.envers.Audited;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;@Audited
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Entity
@EntityListeners({AuditingEntityListener.class, AuditingEntityListener.class})
@MappedSuperclass
@Table(name = "book_store")
public class BookStore implements Serializable {private static final long serialVersionUID = 1L;@Id@org.springframework.data.annotation.Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "name") private String name;@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)@JoinTable(name = "book_store_author",joinColumns =@JoinColumn(name = "book_stores_id", referencedColumnName = "id"),inverseJoinColumns =@JoinColumn(name = "authors_id", referencedColumnName = "id"))private Set<Author> authors = new HashSet<>();public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<Author> getAuthors() {return authors;}public Author addAuthor(Author author) {this.authors.add(author);return this;}public Author removeAuthor(Author author) {this.authors.remove(author);return this;}public void setAuthors(Set<Author> authors) {this.authors = authors;}
}@Audited
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Entity
@EntityListeners({AuditingEntityListener.class, AuditingEntityListener.class})
@MappedSuperclass
@Table(name = "author")
public class Author implements Serializable {private static final long serialVersionUID = 1L;@Id@org.springframework.data.annotation.Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "name") private String name;@OneToMany(cascade = {CascadeType.ALL, CascadeType.PERSIST, CascadeType.MERGE},fetch = FetchType.LAZY, orphanRemoval = true)@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)@JoinColumn(name = "author_id")private Set<Book> books = new HashSet<>();public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<Book> getBooks() {return books;}public Book addBook(Book book) {this.books.add(book);book.setAuthor(this);return this;}public Book removeBook(Book book) {this.books.remove(book);book.setAuthor(null);return this;}public void setBooks(Set<Book> books) {this.books = books}
}@Audited
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Entity
@EntityListeners({AuditingEntityListener.class, AuditingEntityListener.class})
@MappedSuperclass
@Table(name = "book")
public class Book implements Serializable {private static final long serialVersionUID = 1L;@Id@org.springframework.data.annotation.Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "name") private String name;@ManyToOne(optional = false)@JoinColumn(nullable = false)private Author author;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Author getAuthor() {return author;}public void setAuthor(Author author) {this.author = author;}
}

当尝试创建一个书店,内含两个作者,每个作者三本书的时候,程序抛出了第一个错误:

A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance ...

Google了半天,不少人碰到了同样的问题,但没有人讲清楚根本原因是什么,只是建议将方法setAuthors()做如下修改:

public void setAuthors(Set<Author> authors) {this.authors.clear();this.authors.addAll(authors);
}

我照着修改了下,果然有效。但为啥直接给成员authors赋一个新的实例要出错,而修改其内容却不会?完全搞不清楚Spring Boot在背后检查了什么,以后有空还是要深挖一下Spring Boot的代码。

然而,在后续测试时,又碰到了第二个错误:

JSON parse error: Cannot invoke "java.util.Collection.iterator()" because "c" is null

又Google了一天半,终于发现了原因:setAuthors方法里,没有检查参数authors。若它为null,就会引发这个错误。遂继续修改setAuthors():

public void setAuthors(Set<Author> authors) {this.authors.clear();if (authors != null) {this.authors.addAll(authors);}
}

以防万一,按同样的方式修改Author.setBooks():

public void setBooks(Set<Book> books) {this.books.clear();if (books != null) {this.books.addAll(books);}
}

至此,终于解决了上述两个错误。

解决这两个错误的难点在于,哪怕我把log leve调到最低,程序都只是输出了一行错误信息,没有任何相关的stacktrace,导致我无法迅速定位相关代码。而且这两个错误都是在执行RESTful API callback函数之前就触发了,只能在Spring Boot的代码里打断点,调试起来很不方便。

更多推荐

两个难搞的Java Error/Exception

本文发布于:2023-12-03 08:28:38,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1653217.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:两个   Java   Exception   Error

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!