我使用Spring Data JPA爲一個小項目列出一些信息。我有一個類LogEntry,它表示我的GUI上的一個網格中的一行。其他類用於添加/顯示更詳細的信息,如上傳/下載文件的能力。我將文件數據和元信息分隔到兩個類/表中。我的課的關係是這樣的:LogEntry
- >Comment
- >FileReference
- >FileData
Spring Data JPA不能與CascaseType.PERSIST和@OneToOne一起使用
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;
}
}
有了這種分離我就可以讀取所有LogEntry
•不用加載從數據庫中每一個文件,但我還是能顯示一個文件的元信息並提供一種下載方式。我在每個關係上使用CascadeType.ALL。這工作得很好,直到我試圖改變已存在的Comment
中的一些數據。該應用程序試圖保存一個FileReference
,其空引用爲FileData
,這是不允許的。然後我試圖改變的關係FileReference
- >FileData
到CascadeType.PERSIST
,但這會導致一個異常時,我嘗試保存Comment
org.springframework.orm.jpa.JpaObjectRetrievalFailureException:無法找到..FileData與ID 123;嵌套的例外是javax.persistence.EntityNotFoundException:無法找到..FileData ID爲PersistentStringObjectKey 123
似乎春天的數據不能處理,沒有CascadeType.MERGE
。我想到的唯一兩個解決方案是,我使用CascadeType.ALL
,當我必須更改和更新Comment
我加載FileData
所有FileReferences
,然後保存Comment
或者我沒有使用CascadeType.ALL並創建一個DAO,我在其中保存在存儲「主」對象之前,每個對象的每個引用。但這根本不好。
問題: 有誰知道如何使用CasecadeType
S上的正確的方式來實現自己的目標不加載每個選擇FileData
,而不是更改保存到其他實體之前預裝了嗎?
首先,Spring是無關緊要的。你的JPA提供者是Hibernate,而不是Spring。其次,問題在於代碼,而您沒有發佈它。要獲得對現有FileData的引用而不加載它,只需使用'EntityManager.getReference()'(或'JpaRepository.getOne()') –
我使用彈簧數據jpa,所以我不直接使用JPA。 https://開頭github上。/ spring-projects/spring-data-jpa-examples/blob/master/spring-data-jpa-example/src/main/java/org/springframework/data/jpa/example/repository/custom/UserRepository.java I將編輯問題和代碼如何訪問我的實體。我想獲得'LogEntry'列表,而不是一個'FileData'沒有加載 – lrxw
是的,因此我的建議是使用JpaRepository.getOne()。 JpaRepository是Spring-data-jpa中的一個類。 –