Adding this question for documentation purpose, and to check if there is any alternative solution.
I have an entity which has a composite key defined using @IdClass
data class TemplateId(var id: Long? = null, var version: Int = 0) : Serializable
@Entity
@IdClass(TemplateId::class)
data class Template(
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
var id: Long? = null,
@Id
@Column(name = "version")
var version: Int
//Other columns
)
Idea is to have same ID for different versions of the Template
. Using Sequence generator works as expected while inserting new template. But when I try to insert a new version row with same ID, @GeneratedValue
overrides the given value and autoincrements to new value. Solution mentioned in JPA: Override Auto generated ID does not work.
I tried out following options and none worked.
As mentioned in the question, cannot use @GeneratedValue
as it replaces the given value
Cannot replace @SequenceGenerator
with custom generator ( @GenericGenerator
), doesn't work with composite key. It tries to cast Long value to IdClass TemplateId
I am using Postgres, so tried using column type SERIAL
for id
. This does not work with IDENTITY GenerationType on composite key. There is an existing issue: HHH-9662
Cannot use DB auto-increment with NULL value, postgres gives constraint violation error
"insertable"=false/ "updatable"=false
on id
column does not work for @Id
columns
Similarly tried using hibernate's @DynamicInsert
so that it will skip null column values in insert query, but even that doesn't work with @Id
Finally had to override the save
function of Spring's JpaRepository
to make it work
interface CustomTemplateRepository<S> {
fun <E: S> save(entity: E): E
fun <E: S> saveAndFlush(entity: E): E
}
class TemplateRepositoryImpl(
private val jdbcTemplate: NamedParameterJdbcTemplate,
@PersistenceContext private val entityManager: EntityManager
) : CustomTemplateRepository<Template> {
override fun <E : Template> save(entity: E): E {
if(entity.id == null)
entity.id = jdbcTemplate.queryForObject("select nextval('sequence_generator')",
mutableMapOf<String, Any>(), Long::class.java)
entityManager.persist(entity)
return entity
}
override fun <E : Template> saveAndFlush(entity: E): E {
return save(entity).also {
entityManager.flush()
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.