Czar
08/30/2019, 11:34 AMval entity = repository.getOne(entityId)
val entityId = checkNotNull(entity.id) { "Entity id cannot be null if it is retrieved from the database" }
all over the place. In the new project first we thought of using contracts, but their restrictions make them useless for this case, so this more crude idea was born:
abstract class BaseEntity<T : Serializable> {
/**
* Direct use of `_dbId` is strongly discouraged in business level code, this should only be used on the persistence
* level by the framework and related infrastructure code.
*/
@Suppress("PropertyName")
protected abstract val _dbId: T?
/**
* Accessing `id` implies that entity has been retrieved from a repository or crafted with a pre-set identifier.
* If this condition is not met, accessing it will generate an `IllegalStateException`.
*/
@get:Transient
val id: T
get() = checkNotNull(_dbId) { "Entity has not been saved" }
}
Any thoughts? Improvements? Maybe better alternatives?
In this here case, implementation would look like:
@Entity(name = "clients")
class InfoEntity(
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
override val _dbId: Long? = null,
@Column(name = "first_name")
var info: String = ""
) : BaseEntity<Long>()
marstran
08/30/2019, 11:38 AMid
to be inaccessable before saving it to DB, and then non-nullable after. Right?Czar
08/30/2019, 11:39 AMid
solution does not give us the compile time checking (like more advanced contracts would), but at least it reduces boilerplate. Plus to be honest people rarely need id of an unsaved entity anyway, so the chance that someone would try to access it is pretty slim and will probably be caught by the test suite pretty soon.ilyagulya
08/30/2019, 11:57 AMCzar
08/30/2019, 11:58 AMCzar
08/30/2019, 12:05 PM@get:Transient
val id: T by lazy { checkNotNull(_dbId) { "Entity has not been saved" } }
Alowaniak
08/30/2019, 1:18 PM