当前位置: 首页 > 面试题库 >

如何创建支持通用ID(包括自动生成的ID)的通用实体模型类?

东郭海阳
2023-03-14
问题内容

我有三个 种类的 对表的主键:

  • INT自动生成的主键,使用AUTO_INCREMENT数据库供应商(MySQL)的容量
  • CHAR(X) 主键,用于将用户可读的值存储为键(其中X是数字,并且50 <= X <= 60)
  • 复杂的主键,由表的2或3个字段组成。

另外,可能存在(或不存在)一些字段:

  • 版本,INT字段。
  • createdBy VARCHAR(60)字段和lastUpdatedBy VARCHAR(60)字段(还有更多字段,但这些涵盖了基本示例)。

以上示例:

  • 表格1
    • id int主键auto_increment
    • 版本int
    • 值char(10)
    • 由varchar(60)创建
    • lastUpdatedBy varchar(60)
  • 表2
    • id char(60)主键
    • shortDescription varchar(20)
    • longDescription varchar(100)
  • 表3
    • field1 int主键
    • field2 int主键
    • 十进制数(10,5)
    • 版本int

考虑到所有这些,我需要创建一组通用类来支持这些要求,并允许使用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;
}

我目前正在测试保存的实例Table1Table2。我有以下代码:

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并得到了相同的错误消息

我如何重塑这些类以支持这些要求?甚至更好的是,我如何提供一种取决于我所保存实体的密钥的生成策略,该策略可以由我自动生成或提供?

涉及的技术:

  • Java SDK 8
  • hibernate4.3.6
  • JPA 2.1
  • MySQL和Postgres数据库
  • 操作系统:Windows 7 Professional

注意:为了可以得到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";
     }


}


 类似资料:
  • 问题内容: 修改了 整个帖子。 我正在尝试通过Fiddler发布以下JSON POST请求: 但是我收到此错误: 尽管如果我随请求手动发送一个随机ID,那么一切都很好。像这样: 为什么实体框架不生成ID并自动递增ID?我的POCO课程如下: 这是控制器方法。在调试模式下,我通过Fiddler发送请求时,它在处中断并给出了上面所看到的错误。 怎么了? 解 将字符串ID改为int并删除数据注释。仍遵循

  • 问题内容: 有人知道如何从1开始生成,以便下一个对象具有2,依此类推吗? 我尝试了以下方法,但不起作用: 问题答案: 您需要一个 静态的 类成员来跟踪上次使用的索引。确保还实现一个复制构造函数: 更新: 正如@JordanWhite建议的那样,您可能希望使static计数器成为 atomic ,这意味着可以安全地同时使用(即一次在多个线程中使用)。为此,将类型更改为: 增量读取和复位操作变为:

  • 问题内容: 嗨,我编写了这样的代码 但是我从DAO手动设置了它,例如“ e.setUserID(01);”。否则将不插入行是否有任何过程来获取ID值并检索自动生成的值。我想我会得到一些帮助 问题答案: 采用

  • 问题内容: 我需要一个创建对象的类,为每个创建的对象分配一个ID。通常,此ID是该类的int属性。我希望每次创建一个对象时都增加该值(ID),然后将其分配给从1开始的那个对象。这让我感到震惊,我需要一个静态int属性。 如何初始化此静态属性? 我是否应该创建一个单独的方法来进行ID的增量(作为ID生成器),该增量在构造函数内部调用? 通常,最有效和精心设计的方法是什么? 问题答案: 就像您提到的I

  • 问题内容: 我在Employee类中有以下定义 现在,我想使用现有员工ID导入现有员工。即使在保存之前设置了员工ID,也会忽略分配的ID,并存储自动递增的ID。我们如何覆盖呢? 问题答案: 我编写了自己的生成器来解决此问题。 并像这样使用它:(替换包名)

  • 问题内容: 我正在使用JPA(Hibernate的实现)来注释实体类,以将其持久化到关系数据库(MySQL或SQL Server)。有没有一种简单的方法可以从带注释的类自动生成数据库模式(表创建脚本)? 我仍处于原型制作阶段,并期望频繁的模式更改。我希望能够从带注释的代码中指定和更改数据模型。Grails的相似之处在于它从域类生成数据库。 问题答案: 您可以使用Hibernate中的hbm2ddl