java模型给泛型,如何创建支持泛型id的通用实体模型类,包括自动生成的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 implements Serializable {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

protected T id;

}

@MappedSuperclass

public abstract class VersionedEntity extends BaseEntity {

@Version

protected int version;

}

@MappedSuperclass

public abstract class MaintainedEntity extends VersionedEntity {

@Column

protected String createdBy;

@Column

protected String lastUpdatedBy;

}

@Entity

public class Table1 extends MaintainedEntity {

@Column

private String value;

}

@Entity

public class Table2 extends BaseEntity {

@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 implements Serializable {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

protected T id;

@PrePersist

public void ensureIdAssigned() {

ensureIdAssignedInternal();

}

public abstract void ensureIdAssignedInternal();

}

@MappedSuperclass

public abstract class AutoIdMaintaintedEntity extends MaintainedEntity { // 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 {

@Column

private String value;

}

@Entity

public class Table2 extends BaseEntity {

@Column

private String shortDescription;

@Column

private String longDescription;

public void ensureIdAssignedInternal() {

this.id = generateMyTextId();

}

private String generateMyTextId() {

return "text id";

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值