我使用Spring Data JPA为一个小项目列出一些信息。我有一个LogEntry类,它代表我GUI上网格中的一行。其他类用于添加/显示更详细的Informationen,例如上载/下载文件的功能。我将文件数据和元信息分成两个类/表。我的班级关系如下:LogEntry
- > Comment
- > FileReference
- > FileData
FileReference.java
@Entity
public class FileReference extends AbstractEntity {
private static final long serialVersionUID = 3942449578983368585L;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false)
private FileData fileData;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private int size;
}
FileData.java
@Entity
public class FileData extends AbstractEntity {
private static final long serialVersionUID = 6706563782575452010L;
@Lob
byte[] byteArray;
}
LogEntryRepo.java
public interface LogEntryRepo<LogEntry> extends JpaRepository<LogEntry, ObjectKey> {
}
访问我的实体
@Component
@Transactional(readOnly = true)
public class LogEntryServiceImpl implements LogEntryService {
@Autowired
LogEntryRepo repo;
@Autowired
FileReferenceRepo fileReferenceRepo;
/**
* save a changed LogEntry
*/
@Override
@Secured(Roles.ROLE_WRITE)
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void saveLogEntry(LogEntry logEntry) {
if (logEntry != null) {
LogEntry one = repo.getOne(logEntry.getObjectKey());
if (one != null) {
if (one.isAudited()) {
throw new AlreadyAuditedException();
}
}
}
repo.save(logEntry);
}
@Override
@Secured(Roles.ROLE_READ_ONLY)
@Transactional(readOnly = true)
public List<LogEntry> loadAll() {
List<LogEntry> findAll = repo.findAll();
for (LogEntry logEntry : findAll) {
setNullForFileData(logEntry); // avoid serialization problems with lazy loading proxies
}
return findAll;
}
@Override
@Secured(Roles.ROLE_READ_ONLY)
@Transactional(readOnly = true)
public FileReference loadFileData(ObjectKey key) {
FileReference fileReference = fileReferenceRepo.findOne(key);
// fileData ist lazy loaded. call once to load it from db.
fileReference.getFileData().getObjectKey();
return fileReference;
}
}
通过这种分离,我可以在不加载db中的每个文件的情况下读取所有LogEntry
,但我仍然能够显示文件的元信息并提供下载它的方法。我在每个关系上使用CascadeType.ALL。这非常有效,直到我尝试更改已存在的Comment
中的某些数据。该应用程序尝试将FileReference
保存为FileData
,但不允许使用FileReference
。然后我尝试将关系FileData
- &gt; CascadeType.PERSIST
更改为Comment
,但当我尝试保存CascadeType.MERGE
org.springframework.orm.jpa.JpaObjectRetrievalFailureException:无法找到ID为123的..FileData;嵌套异常是javax.persistence.EntityNotFoundException:无法找到具有id PersistentStringObjectKey的..FileData 123
似乎spring数据无法处理没有CascadeType.ALL
的情况。我想到的唯一两个解决方案是,我使用Comment
,当我需要更改和更新FileData
时,我为所有FileReferences
加载Comment
,然后保存{{ 1}}或者我不使用CascadeType.ALL并在存储“main”对象之前创建一个DAO,其中我保存每个对象的每个引用。但这根本不好。
问题:
有没有人知道如何使用CasecadeType
正确的方法来实现我的目标,不在每个选择上加载FileData
而不是在将更改保存到其他实体之前预加载它?
答案 0 :(得分:1)
因为java BLOB
插入BD
需要插入和更新而不是仅插入,因此需要cascade={CascadeType.PERSIST,CascadeType.MERGE}
。