gpt4 book ai didi

mysql - 使用 CrudRepository 删除带有集合的实体时,Hibernate-envers 抛出异常

转载 作者:行者123 更新时间:2023-11-29 03:29:46 26 4
gpt4 key购买 nike

我想知道是否有其他人在使用接口(interface) CrudRepository 的 Spring-boot 应用程序中将 hibernate-envers 与 mysql 一起使用,并且在删除带有集合的实体时遇到了麻烦。我将一个示例应用程序与一个演示生成的异常的测试放在一起。

示例可以从https://github.com/LindesRoets/test-delete.git 中复制

你需要运行 mysql 和一个名为 test_delete 的数据库

CREATE DATABASE IF NOT EXISTS `test_delete` DEFAULT CHARACTER SET utf8;

运行测试

mvn test

您应该看到以下异常:

    2015-08-11 21:36:28.725 ERROR 3855 --- [           main] org.hibernate.AssertionFailure           : HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): java.lang.NullPointerException
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 4.926 sec <<< FAILURE! - in com.dcp.test.AuthorRepositoryTest
testAuthorCRUD(com.dcp.test.AuthorRepositoryTest) Time elapsed: 0.163 sec <<< ERROR!
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.engine.internal.StatefulPersistenceContext.getLoadedCollectionOwnerOrNull(StatefulPersistenceContext.java:756)
at org.hibernate.event.spi.AbstractCollectionEvent.getLoadedOwnerOrNull(AbstractCollectionEvent.java:75)
at org.hibernate.event.spi.InitializeCollectionEvent.<init>(InitializeCollectionEvent.java:36)
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1931)
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:558)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:260)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294)
at java.util.AbstractCollection.addAll(AbstractCollection.java:343)
at org.hibernate.envers.internal.entities.mapper.relation.AbstractCollectionMapper.mapCollectionChanges(AbstractCollectionMapper.java:162)
at org.hibernate.envers.internal.entities.mapper.relation.AbstractCollectionMapper.mapModifiedFlagsToMapFromEntity(AbstractCollectionMapper.java:212)
at org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper.map(MultiPropertyMapper.java:105)
at org.hibernate.envers.internal.synchronization.work.DelWorkUnit.generateData(DelWorkUnit.java:66)
at org.hibernate.envers.internal.synchronization.work.AbstractAuditWorkUnit.perform(AbstractAuditWorkUnit.java:76)
at org.hibernate.envers.internal.synchronization.AuditProcess.executeInSession(AuditProcess.java:119)

下面是示例应用程序中出现的所有源代码。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>


<groupId>com.test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test-delete</name>
<description></description>


<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
</parent>


<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.test.Application</start-class>
<java.version>1.8</java.version>
<spring-boot-version>1.2.5.RELEASE</spring-boot-version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<includes>
<include>**/*Test*.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot-version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${spring-boot-version}</version>
</dependency>


<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>


<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
</dependency>
</dependencies>

</project>

application.properties

spring.datasource.url = jdbc:mysql://localhost:3306/test_delete
spring.datasource.username =
spring.datasource.password =
# Specify the DBMS
spring.jpa.database = MYSQL
spring.datasource.driverClassName = com.mysql.jdbc.Driver

# Show or not log for each sql query
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = create

# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

#envers
spring.jpa.properties.org.hibernate.envers.global_with_modified_flag=true
spring.jpa.properties.org.hibernate.envers.store_data_at_delete=true

应用程序.java

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

BaseEntity.java

@MappedSuperclass
@Audited
public abstract class BaseEntity implements Serializable {

@GeneratedValue(generator = "guid")
@GenericGenerator(name = "guid", strategy = "guid")
@Column(columnDefinition = "CHAR(36)")
@Id
protected String id;

@Temporal(TemporalType.TIMESTAMP)
protected Date dateCreated = new Date();

public String getId() {
return id;
}

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

public Date getDateCreated() {
return dateCreated;
}

public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}

private static final long serialVersionUID = -8371628134270930829L;
}

Author.java

@Entity
@Audited
public class Author extends BaseEntity{

private String email;

private String name;

@OneToMany(mappedBy = "author")
private List<Book> books = new ArrayList<>();

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getName() {
return name;
}

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

public List<Book> getBooks() {
return books;
}

public void setBooks(List<Book> books) {
this.books = books;
}


}

Book.java

@Entity
@Audited
public class Book extends BaseEntity {

private String title;

private String genre;

@ManyToOne
private Author author;

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getGenre() {
return genre;
}

public void setGenre(String genre) {
this.genre = genre;
}

public Author getAuthor() {
return author;
}

public void setAuthor(Author author) {
this.author = author;
}

}

AuthorRepository.java

@Transactional
public interface AuthorRepository extends CrudRepository<Author, String> {

}

AuthorRepositoryTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class AuthorRepositoryTest {

@Autowired
private AuthorRepository authorRepo;

@Test
public void testAuthorCRUD() {
Author author = new Author();
author.setName("Test Name");
author.setEmail("test@mail.com");

Author savedAuthor = authorRepo.save(author);

Assert.assertNotNull(savedAuthor);

authorRepo.delete(savedAuthor);
}

}

如果您从实体类 Book、Author 和 BaseEntity 中注释掉 @Audited,测试就会顺利通过。

有谁知道如何使删除功能与 envers 一起使用?

最佳答案

通过反复试验,我发现有两种方法可以使删除操作按照问题中的说明进行。

您可以指定要预先加载的集合

@OneToMany(mappedBy = "author", fetch = FetchType.EAGER)

或者你可以级联删除操作

@OneToMany(mappedBy = "author", cascade = CascadeType.REMOVE)

这是使测试通过问题中指定的所需的最低配置。

关于mysql - 使用 CrudRepository 删除带有集合的实体时,Hibernate-envers 抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31954879/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com