-
Notifications
You must be signed in to change notification settings - Fork 378
Closed as not planned
Labels
has: design-decisionAn issue that contains a design decision about its topicAn issue that contains a design decision about its topicstatus: invalidAn issue that we don't feel is validAn issue that we don't feel is valid
Description
Assume the following classes (with Lombok @Data annotations):
public interface PersistableEntity {
long getId();
void setId(long id);
}
@Data
public class Base implements PersistableEntity {
@Id
long baseId;
String name;
@CreatedDate
Timestamp created;
@MappedColumn(idColumn="baseId", keyColumn="baseId")
SequentialSet<Sub> items;
@Override
long getId() {
return baseId;
}
@Override
void setId(long id) {
this.baseId = id;
}
}
@Data
public class Sub implements PersistableEntity{
@Id
long subId;
long baseId;
String data;
@CreatedDate
Timestamp created;
@Override
long getId() {
return subId;
}
@Override
void setId(long id) {
this.subId = id;
}
}We also have a BeforeConvertCallback for each type, which gets the id from a PostgreSQL sequence.
@Log4j2
@Component
public class AbstractBeforeConvertCallback<T extends PersistableEntity> implements BeforeConvertCallback<T> {
private static final String SEQUENCE_ID_REQUEST = "SELECT nextval('%s')";
protected final JdbcTemplate jdbcTemplate;
@Override
public @NotNull T onBeforeConvert(@NotNull T value) {
log.debug("Converting entity {}", value);
if (value.getId() == DEFAULT_ID) {
value.setId(getNextId());
}
return value;
}
private Long getNextId() {
return jdbcTemplate.queryForObject(String.format(SEQUENCE_ID_REQUEST, getSequence()), Long.class);
}
}
@Component
public class BaseBeforeConvertCallback extends AbstractBeforeConvertCallback<Base> {
private static final String SEQUENCE = "sq_base";
public BaseBeforeConvertCallback(JdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
}
@Override
protected String getSequence() {
return SEQUENCE;
}
}
@Component
public class SubBeforeConvertCallback extends AbstractBeforeConvertCallback<Sub> {
private static final String SEQUENCE = "sq_sub";
public SubBeforeConvertCallback(JdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
}
@Override
protected String getSequence() {
return SEQUENCE;
}
}Let's consider a test example (in Groovy) for BaseRepository:
def saveObject = new Base(baseId: 1, name: 'SomeName', items: [new Sub(subId: 1, data: 'data')]
baseRepository.save(saveObject)This results in an erroneous query being generated for the sub item. Here is a part of the resulting stacktrace (let's assume that the next value generated for the Base sequence was 5):
Batch entry 0 INSERT INTO "sub" ("data", "base_id", "sub_id", "created") VALUES (('data'), (5), (NULL), (NULL))
So, what I assume is happening here:
- The Base entity is being properly saved
- The repository then attempts to save the Sub entity, but fails, since the BeforeConvertCallback and the auditing logic are not invoked for it.
I'm not sure, whether the repository is intended to work like this at all (although the fact that it attempts to save the mapped entities certainly hints that it might have been intended), but this seems like an oversight. Or, perhaps, it was a structural issue on my part?
Thank you.
Metadata
Metadata
Assignees
Labels
has: design-decisionAn issue that contains a design decision about its topicAn issue that contains a design decision about its topicstatus: invalidAn issue that we don't feel is validAn issue that we don't feel is valid