我在将新行插入MySQL数据库时出现问题。我正在使用Spring Boot和Spring Boot Data JPA。
由于MySQL不支持序列,我决定尝试创建自己的序列生成器表。这基本上就是我所做的。
sequences
表,它使用了一个自动增量字段(用作我的表格的id')。sequences_nextvalue()
,它插入sequences
表并返回新的自动增加的id。sequences_nextvalue()
的结果替换id字段。因此,在插入新行时,此功能正常。我在所有表格中获得了独特的ID。我遇到的问题是我的JPA实体。
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractBaseClass {
@Id
private Integer id = -1;
...
}
@Entity
public class ConcreteClass1 extends AbstractBaseClass {
...
}
@Entity
public class ConcreteClass2 extends AbstractBaseClass {
...
}
我希望能够从抽象基类中进行查询,因此我已将@Id
列放在该类中,并将@Entity
与InheritanceType.TABLE_PER_CLASS
一起使用。我还将id初始化为-1,因为需要id来从我的spring crud存储库调用save()
。
在调用我的Spring数据save()
的{{1}}函数后,CrudRepository
的-1正确地被MySQL触发器替换,但由id
返回的结果实体没有& #39; t返回新的id,但保留-1。查看SQL日志后,插入后不会调用select语句来获取新id,而是返回原始实体。
是否可以强制Hibnerate在插入后重新选择实体,以便在您不使用save()
时获取新ID?
非常感谢任何帮助。
答案 0 :(得分:0)
只想提供有关此问题的更新。这是我的解决方案。
我没有创建MySQL TRIGGER
来替换id
上的INSERT
,而是创建了一个执行IdentifierGenerator
的{{1}}的Hibernate CallableStatement
获取并返回一个新的id。
我的抽象基类现在看起来像这样。
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractBaseClass {
@Id
@GenericGenerator(name="MyIdGenerator", strategy="com.sample.model.CustomIdGenerator" )
@GeneratedValue(generator="MyIdGenerator" )
private Integer id;
...
}
我的发电机看起来像这样。
public class CustomIdGenerator implements IdentifierGenerator {
private Logger log = LoggerFactory.getLogger(CustomIdGenerator.class);
private static final String QUERY = "{? = call sequence_nextvalue()}";
@Override
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
Integer id = null;
try {
Connection connection = session.connection();
CallableStatement statement = connection.prepareCall(QUERY);
statement.registerOutParameter(1, java.sql.Types.INTEGER);
statement.execute();
id = statement.getInt(1);
} catch(SQLException e) {
log.error("Error getting id", e);
throw new HibernateException(e);
}
return id;
}
}
仅供参考
sequences
表。
CREATE TABLE sequences (
id INT AUTO_INCREMENT PRIMARY KEY,
thread_id INT NOT NULL,
created DATETIME DEFAULT CURRENT_TIMESTAMP
) ^;
sequence_nextvalue
功能
CREATE FUNCTION sequence_nextvalue()
RETURNS INTEGER
NOT DETERMINISTIC
MODIFIES SQL DATA
BEGIN
DECLARE nextvalue INTEGER;
INSERT INTO sequences (thread_id) VALUE (CONNECTION_ID());
SELECT id FROM sequence_values ORDER BY created DESC LIMIT 1 INTO nextvalue;
RETURN nextvalue;
END ^;