Business logic in service method
Set&lt;Asset&gt; transferredAssets = assetRepository.getAll(transfer.getTransferredAssets());
for (Asset asset : transferredAssets) { ... }


Since the transfer isn't done yet, and also to prevent ambiguity post-transfer, may I suggest renaming the method to getAssets()? You can also inline the call:

for (Asset asset : assetRepository.getAll(transfer.getTransferredAssets())) { ... }


Two minor improvements I can suggest for the snippet below:


It's safe to compare enums by ==.
Have a transfer(TransferType, long) method in Asset so that the toggling is done within Asset: callers only need to supply the TransferType value.




if (TransferType.TEMPORARY.equals(transfer.getTransferType())) {
    asset.transferTemporarily(transfer.getReceiver());
} else {
    asset.transferPermanently(transfer.getReceiver());
}


Since the use of realized and cancelled are just opposites of each other, you may want to consider having just a single boolean field, to keep the implementation simpler.

if (accepted) {
    this.realized = true;
} else {
    this.cancelled = true;
}


In Asset:

public void transferTemporarily(long receiverId) {
    this.currentOwnerId = receiverId;
    this.unblockIfBlocked();
}

public void transferPermanently(long receiverId) {
    this.actualOwnerId = receiverId;
    this.currentOwnerId = receiverId;
    this.unblockIfBlocked();
}


This can be slightly simplified as:

public void transferTemporarily(long receiverId) {
    this.currentOwnerId = receiverId;
    this.unblockIfBlocked();
}

public void transferPermanently(long receiverId) {
    transferTemporarily(receiverId);
    this.actualOwnerId = receiverId;
}


Alternatively, if reading temporarily inside a permanent method is slightly confusing, have a new method setCurrentOwnerAndUnblock() to do that instead...