如何创建支持泛型id的通用实体模型类,包括自动生成的ID? [英] How to create a generic entity model class that supports generic id including auto generated ids?

查看:260
本文介绍了如何创建支持泛型id的通用实体模型类,包括自动生成的ID?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有三种用于表格的主键:




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



此外,还有一些可能存在的字段组不是):


  • 版本, INT 字段

  • createdBy, VARCHAR(60)字段和lastUpdatedBy, VARCHAR(60)字段字段,但这些都包含一个基本示例)。


    以上示例:


    • 表1

      • id int主键auto_increment

      • version int

      • value char(10)

      • createdBy varchar(60)

      • lastUpdatedBy varchar(60)


    • 表2

      • id char(60)主键

      • shortDescription varchar(20)
      • longDescription varchar(100)

    • 表3

      • field1诠释主键

      • field2诠释主键

      • 十进制(10,5)
      • 版本int




    考虑到这一切,我需要创建一个通用的一组类来支持这些需求,并允许使用Hibernate 4.3和JPA 2.1的CRUD操作。



    这里是我的当前模型(getters / setters避免缩短代码示例):

      @MappedSuperclass 
    public abstract class BaseEntity< T>实现Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected T id;
    }

    @MappedSuperclass
    public abstract class VersionedEntity< T>扩展BaseEntity< T> {
    @版本
    保护int版本;
    }

    @MappedSuperclass
    公共抽象类MaintainedEntity< T>扩展了VersionedEntity< T> {
    @Column
    protected String createdBy;
    @Column
    保护字符串lastUpdatedBy;
    }

    @Entity
    public class Table1 extends MaintainedEntity< Long> {
    @Column
    私有字符串值;
    }

    @Entity
    public class Table2 extends BaseEntity< String> {
    @Column
    private String shortDescription;
    @Column
    private String longDescription;
    }

    我正在测试的保存实例Table1 Table2 。我有以下代码:

      SessionFactory sf = HibernateUtils.getSessionFactory(); 
    Session session = sf.getCurrentSession();
    session.beginTransaction();

    Table1 newTable1 = new Table1();
    newTable1.setValue(foo);
    session.save(newTable1); //作品

    Table2 newTable2 = new Table2();
    //在这里我想手动设置ID
    newTable2.setId(foo_id);
    newTable2.setShortDescription(short desc);
    newTable2.setLongDescription(long description);
    session.save(newTable2); //失败

    session.getTransaction()。commit();
    sf.close();

    尝试保存 Table2 时失败并且我得到以下错误:

    pre $ 引起:java.sql.SQLException:字段'id'没有默认值
    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

    • Hibernate 4.3.6

    • JPA 2.1

    • MySQL和Postgres数据库

    • 操作系统:Windows 7 Professional


    注意:上述可能(也可能会改变)以支持其他JPA 2.1实现,如EclipseLink。

    解决方案

您可以解决方法强制派生类实现将确保Id被分配并使用@PrePersist注释此方法的方法。您可以为自动生成Id的类提供默认实现。



Somethig like:

  @MappedSuperclass 
public abstract class BaseEntity< T>实现Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected T id;

@PrePersist
public void ensureIdAssigned(){
ensureIdAssignedInternal();
}


public abstract void ensureIdAssignedInternal();
}


@MappedSuperclass
公共抽象类AutoIdMaintaintedEntity< T>扩展了MaintainedEntity< T> {//为BaseEntity超类中的@GeneratedValue(strategy = GenerationType.IDENTITY)生成的Id提供实体的默认实现
public void ensureIdAssignedInternal(){
//此处没有任何内容,因为Id将被自动分配
}
}

@Entity
public class Table1 extends AutoIdMaintaintedEntity< Long> {
@Column
私有字符串值;
}

@Entity
public class Table2 extends BaseEntity< String> {
@Column
private String shortDescription;
@Column
private String longDescription;

public void ensureIdAssignedInternal(){
this.id = generateMyTextId();



private String generateMyTextId(){
returntext id;
}


}


I have three kinds of primary keys for tables:

  • INT auto generated primary key which use AUTO_INCREMENT capacity from database vendor (MySQL)
  • CHAR(X) primary key to store a user readable value as key (where X is a number and 50 <= X <= 60)
  • Complex primary keys, composed by 2 or 3 fields of the table.

Also, there are some group of fields that may be present (or not):

  • version, INT field.
  • createdBy, VARCHAR(60) field, and lastUpdatedBy, VARCHAR(60) field (there are more fields but these covers a basic example).

Some examples of above:

  • Table1
    • id int primary key auto_increment
    • version int
    • value char(10)
    • createdBy varchar(60)
    • lastUpdatedBy varchar(60)
  • Table2
    • id char(60) primary key
    • shortDescription varchar(20)
    • longDescription varchar(100)
  • Table3
    • field1 int primary key
    • field2 int primary key
    • amount decimal(10, 5)
    • version int

With all this in mind, I need to create a generic set of classes that supports these requirements and allows CRUD operations using Hibernate 4.3 and JPA 2.1.

Here's my current model (getters/setters avoided to shorten the code sample):

@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;
}

I'm currently testing save instances of Table1 and Table2. I have the following code:

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();

It fails when trying to save Table2 and I get the following error:

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)

The error message is obvious because a CHAR(X) field doesn't have a default value and won't have it (AFAIK). I tried changing the generation strategy to GenerationType.AUTO and got the same error message.

How can I remodel these classes in order to support these requirements? Or even better, how could I provide a generation strategy that depends on the key of the entity I'm saving, which could be auto generated or provided by me?

Involved technologies:

  • Java SDK 8
  • Hibernate 4.3.6
  • JPA 2.1
  • MySQL and Postgres databases
  • OS: Windows 7 Professional

Note: the above may (and probably will) change in order to be supported for other implementations of JPA 2.1 like EclipseLink.

解决方案

You can "workaround" this forcing derived class to implement method which will ensure the Id is assigned and annotate this method with @PrePersist. You can provide default implementation for classes for which the Id will be auto generated.

Somethig like:

@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";
     }


}

这篇关于如何创建支持泛型id的通用实体模型类,包括自动生成的ID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆