如何在不降低将对象存储到数据库的性能的情况下逐字段比较由@Entity注释的class?
How to compare class annotated by @Entity field by field without degrading performance of storing object into db?
我有数据库 class 在 Java
中用 @Entity
注释。
我想比较 class 的 2 个实例,我想按字段比较字段,但从 Hamcrest
中得到错误,指出对象不相等。它会持续存在,除非我在 Eclipse
.
中自动生成 equals
和 hashCode
实体结构如下:
@Entity
@Table(name = "book")
public class Book extends BaseEntity {
@NotNull
@Column
private String title;
}
和
@MappedSuperClass
class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
为了简单起见,我省略了所有的 getter 和 setter。
示例代码我如何使用上面的实体:
public void updateBookTitles(bookIds) {
List<Book> books = bookRepository.findByBookIds(bookIds);
books.forEach((book) -> {
book.setTitle("Example: " + book.getTitle());
});
bookRepository.saveAll(books);
}
测试时:
@Test
public void updateSingleBookTitle() {
Book book = new Book();
book.setId(1L);
book.setTitle("Stack Overflow manual");
when(bookRepository.findByBookIds(Arrays.asList(1L))).thenReturn(Arrays.asList(book));
updateBookTitles(Arrays.asList(1L));
Book expectedBook = new Book();
expectedBook.setId(1L);
expectedBook.setTitle("Stack Overflow manual");
verify(bookRepository, times(1)).saveAll(Arrays.asList(expectedBook))
}
所以,我的问题来了。除了自动生成 equals
和 hashCode
之外,还有什么方法可以让对象在测试期间相等,并且在存储到数据库时不会降低性能。据我所知,目前对象是由 id
字段而不是所有字段检查的。
对于这样的数据实体,您可能想使用像 Lombok https://projectlombok.org/ 这样的东西。比如 equals、hashCode、getters 和 setters。
可以使用samePropertyValuesAs
方法:
Book book1 = new Book();
Book book2 = new Book();
assertThat(book1, samePropertyValuesAs(book2));
这将逐个字段地比较您的对象,并对它们之间的相等性执行断言。如果您需要忽略某些字段 - 查看 Shazamcrest - Reusable Hamcrest matchers suitable for automated testing.
更新 1:
尝试使用下一个代码:
verify(bookRepository, times(1)).saveAll(argThat(new ArgumentMatcher<List<Book>>() {
@Override
public boolean matches(Object argument) {
List<Book> bookToCheck = (List<Book>) argument;
assertThat(bookToCheck.get(0), sameAsBean(expectedBook));
return true;
}
}));
更多信息:ArgumentMatcher
我有数据库 class 在 Java
中用 @Entity
注释。
我想比较 class 的 2 个实例,我想按字段比较字段,但从 Hamcrest
中得到错误,指出对象不相等。它会持续存在,除非我在 Eclipse
.
equals
和 hashCode
实体结构如下:
@Entity
@Table(name = "book")
public class Book extends BaseEntity {
@NotNull
@Column
private String title;
}
和
@MappedSuperClass
class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
为了简单起见,我省略了所有的 getter 和 setter。
示例代码我如何使用上面的实体:
public void updateBookTitles(bookIds) {
List<Book> books = bookRepository.findByBookIds(bookIds);
books.forEach((book) -> {
book.setTitle("Example: " + book.getTitle());
});
bookRepository.saveAll(books);
}
测试时:
@Test
public void updateSingleBookTitle() {
Book book = new Book();
book.setId(1L);
book.setTitle("Stack Overflow manual");
when(bookRepository.findByBookIds(Arrays.asList(1L))).thenReturn(Arrays.asList(book));
updateBookTitles(Arrays.asList(1L));
Book expectedBook = new Book();
expectedBook.setId(1L);
expectedBook.setTitle("Stack Overflow manual");
verify(bookRepository, times(1)).saveAll(Arrays.asList(expectedBook))
}
所以,我的问题来了。除了自动生成 equals
和 hashCode
之外,还有什么方法可以让对象在测试期间相等,并且在存储到数据库时不会降低性能。据我所知,目前对象是由 id
字段而不是所有字段检查的。
对于这样的数据实体,您可能想使用像 Lombok https://projectlombok.org/ 这样的东西。比如 equals、hashCode、getters 和 setters。
可以使用samePropertyValuesAs
方法:
Book book1 = new Book();
Book book2 = new Book();
assertThat(book1, samePropertyValuesAs(book2));
这将逐个字段地比较您的对象,并对它们之间的相等性执行断言。如果您需要忽略某些字段 - 查看 Shazamcrest - Reusable Hamcrest matchers suitable for automated testing.
更新 1:
尝试使用下一个代码:
verify(bookRepository, times(1)).saveAll(argThat(new ArgumentMatcher<List<Book>>() {
@Override
public boolean matches(Object argument) {
List<Book> bookToCheck = (List<Book>) argument;
assertThat(bookToCheck.get(0), sameAsBean(expectedBook));
return true;
}
}));
更多信息:ArgumentMatcher