我有三个 种类的 对表的主键:
INT
AUTO_INCREMENT
CHAR(X)
另外,可能存在(或不存在)一些字段:
VARCHAR(60)
以上示例:
考虑到所有这些,我需要创建一组通用类来支持这些要求,并允许使用Hibernate 4.3和JPA 2.1进行CRUD操作。
这是我当前的模型(避免使用getter / setter来缩短代码示例):
@MappedSuperclass public abstract class BaseEntity<T> implements Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) protected T id; } @MappedSuperclass public abstract class VersionedEntity<T> extends BaseEntity<T> { @Version protected int version; } @MappedSuperclass public abstract class MaintainedEntity<T> extends VersionedEntity<T> { @Column protected String createdBy; @Column protected String lastUpdatedBy; } @Entity public class Table1 extends MaintainedEntity<Long> { @Column private String value; } @Entity public class Table2 extends BaseEntity<String> { @Column private String shortDescription; @Column private String longDescription; }
我目前正在测试保存的实例Table1和Table2。我有以下代码:
Table1
Table2
SessionFactory sf = HibernateUtils.getSessionFactory(); Session session = sf.getCurrentSession(); session.beginTransaction(); Table1 newTable1 = new Table1(); newTable1.setValue("foo"); session.save(newTable1); //works Table2 newTable2 = new Table2(); //here I want to set the ID manually newTable2.setId("foo_id"); newTable2.setShortDescription("short desc"); newTable2.setLongDescription("long description"); session.save(newTable2); //fails session.getTransaction().commit(); sf.close();
尝试保存时失败,Table2并且出现以下错误:
Caused by: java.sql.SQLException: Field 'id' doesn't have a default value at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:996) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3887)
该错误消息很明显,因为CHAR(X)字段没有默认值,并且也没有默认值(AFAIK)。我尝试将生成策略更改为,GenerationType.AUTO并得到了相同的错误消息。
GenerationType.AUTO
我如何重塑这些类以支持这些要求?甚至更好的是,我如何提供一种取决于我所保存实体的密钥的生成策略,该策略可以由我自动生成或提供?
涉及的技术:
注意:为了可以得到JPA 2.1的其他实现(如EclipseLink)的支持,以上内容可能会(可能会)更改。
您可以“强制解决”此强制派生类以实现方法,该方法将确保分配ID并使用@PrePersist对该方法进行注释。您可以为将为其自动生成ID的类提供默认实现。
Somethig喜欢:
@MappedSuperclass public abstract class BaseEntity<T> implements Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) protected T id; @PrePersist public void ensureIdAssigned() { ensureIdAssignedInternal(); } public abstract void ensureIdAssignedInternal(); } @MappedSuperclass public abstract class AutoIdMaintaintedEntity<T> extends MaintainedEntity<T> { // provide default implementation for Entities with Id generated by @GeneratedValue(strategy=GenerationType.IDENTITY) on BaseEntity superclass public void ensureIdAssignedInternal() { // nothing here since the Id will be automatically assigned } } @Entity public class Table1 extends AutoIdMaintaintedEntity<Long> { @Column private String value; } @Entity public class Table2 extends BaseEntity<String> { @Column private String shortDescription; @Column private String longDescription; public void ensureIdAssignedInternal() { this.id = generateMyTextId(); } private String generateMyTextId() { return "text id"; } }