我正在尝试向表中插入行(问题)列表。(比如说'Question_Table')。 整个过程在单个事务中执行。 (即,我必须插入所有问题或不插入)。我正在使用Spring的声明式事务。
我已经为Question_Table定制了ID生成。(参考:Custom id generation)
它适用于第一个问题。但它不适用于第二个问题,因为第一行是未提交的,并且表将为空。我无法将DAO类注入Id生成器,因为它不是Spring托管bean(因此我可以在DAO类中使用读取未提交记录的方法)。
在这种情况下使用的最佳方法是什么。
生成器类
public class IdGenerator implements IdentifierGenerator, Configurable {
private String prefix = "";
private String queryKey = "";
@Override
public Serializable generate(SessionImplementor sessionImpl, Object arg1) throws HibernateException {
long count = (long)sessionImpl.getNamedQuery(queryKey).list().get(0);
System.out.println("COUNT >>> "+count);
long id = count + 1;
if(id == 4) throw new NullPointerException();
String generatedId = prefix + id;
return generatedId;
}
@Override
public void configure(Type arg0, Properties arg1, ServiceRegistry arg2) throws MappingException {
prefix=arg1.getProperty("PREFIX");
queryKey=arg1.getProperty("QUERY_KEY");
}
}
查询:从Question_Table中选择count(*)
答案 0 :(得分:1)
正如我在评论中所述,如果使用字符串和序列的组合没有问题,你可以use this approach。但缺点是,即使删除该表中的所有记录,该值也将始终增加。
如果您坚持使用count,那么解决方案就是手动保存定义您的实体ID。 .save(question, "QSTN_"+(row_count + i));
但您需要能够通过我认为不是问题的row_count
,因为它必须是一次请求。
答案 1 :(得分:0)
我对您的具体问题没有答案,但我想分享一些注意事项。
如果您的id生成依赖于数据库状态,那么必须在数据库级别完成(实现取决于您,自动增量,自定义函数或序列等)...
否则,如果您在应用程序级别执行此操作,则必须遇到并发访问问题,并且必须使用某些锁定或专用事务来缓解它,这会对应用程序性能产生重大影响并可能变为稍后不一致(例如,在添加水平可伸缩性或分片时)。
但是,如果您想在应用层(which can be a very good idea)中生成ID,那么您必须拥有专门用于此任务的独特分布式系统,而该系统不属于您当前的工作单元。
答案 2 :(得分:0)
@Transactional(isolation = Isolation.READ_COMMITTED)
public AccountDto saveAccount(AccountDto accountDto) {
Long accountTypeId = accountDto.getAccountTypeId();
AccountTypes accountTypes = accountTypesDao.getById( accountTypeId ).orElseThrow( NotFoundAppException::new );
account.setAccountName( newAccountName );
account.setAccountType( accountTypes );
...
accountDao.save( account );
accountDao.flush();
// new inserted account id is in the transaction now
return createAccountDtoFrom( account );
}