我正在使用org.hibernate.id.IdentifierGenerator
生成主键列,如下所示。在下面给出的示例中,当前它只是按顺序递增类型INT(11)
(MySQL)的键,即它与MySQL中的auto_increment
类似,但它可以用于生成任何自定义模式的值,如E0001, E0002,E0003 ... E0010 ... E0100 ... E1000 ... E12345 ...
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
public final class TestIdGenerator implements IdentifierGenerator {
@Override
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
try {
Connection connection = session.connection();
PreparedStatement ps = connection.prepareStatement("SELECT MAX(id) AS id FROM test");
ResultSet rs = ps.executeQuery();
if (rs.next()) {
int id = rs.getInt("id");
return id <= 0 ? 1 : id + 1;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
使用上述id生成器的实体Test
:
public class Test implements Serializable {
@Id
@GenericGenerator(name = "test_sequence", strategy = "com.example.TestIdGenerator")
@GeneratedValue(generator = "test_sequence")
@Basic(optional = false)
@Column(name = "id", nullable = false)
private Integer id;
//...
}
然而,这是一个Hibernate特有的功能。有没有办法使提供者不可知,即JPA(2.1)中是否有这样的功能?
我正在使用具有JPA 2.1的Hibernate 5.1.0 final。
这种方法是否会在持久化,合并和删除实体并需要某种锁定时导致一些并发问题?
答案 0 :(得分:2)
你不能像你希望的那样用注释来做。您可以使用@PrePersist
挂钩。
@PrePersist
public void ensureId() {
id = ...
}
也就是说,您可能无法从@PrePersist
方法访问数据库...... JPA 2规范(JSR 317)声明如下:
通常,可移植应用程序的生命周期方法不应调用EntityManager或Query操作,访问其他实体实例或修改同一持久化上下文中的关系。
就实现而言,Hibernate明确禁止它:
回调方法不能调用EntityManager或Query方法!
我的建议:如果需要指定类型,请使用序列并使用单独的列。此外,您始终可以修改SELECT
以撤回您选择的模式:
select 'E' || id as id from schema.table;
或者您可以使用@ PostLoad / @PostPersist撤回瞬态字段&#34; formattedId&#34;:
@PostLoad
@PostPersist
private void setFormattedId() {
this.formattedId = "E" + id;
}