我有三个 种类的 对表的主键:
INT
自动生成的主键,使用AUTO_INCREMENT
数据库供应商(MySQL)的容量CHAR(X)
主键,用于将用户可读的值存储为键(其中X是数字,并且50 <= X <= 60)另外,可能存在(或不存在)一些字段:
INT
字段。VARCHAR(60)
字段和lastUpdatedBy 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
。我有以下代码:
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
并得到了相同的错误消息。
我如何重塑这些类以支持这些要求?甚至更好的是,我如何提供一种取决于我所保存实体的密钥的生成策略,该策略可以由我自动生成或提供?
涉及的技术:
注意:为了可以得到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