我的问题与[1]或[2]中描述的相同。我需要手动设置默认情况下自动生成的值(为什么?导入旧数据)。如[1]中所述,使用Hibernate entity = em.merge(entity)可以解决问题。
Hibernate entity = em.merge(entity)
对我来说不幸的是事实并非如此。我既未收到错误也未收到其他任何警告。该实体只是不会出现在数据库中。我正在使用Spring和Hibernate EntityManager 3.5.3-Final。
它可以通过以下代码在我的项目中运行:
@XmlAttribute @Id @Basic(optional = false) @GeneratedValue(strategy=GenerationType.IDENTITY, generator="IdOrGenerated") @GenericGenerator(name="IdOrGenerated", strategy="....UseIdOrGenerate" ) @Column(name = "ID", nullable = false) private Integer id;
和
import org.hibernate.id.IdentityGenerator; ... public class UseIdOrGenerate extends IdentityGenerator { private static final Logger log = Logger.getLogger(UseIdOrGenerate.class.getName()); @Override public Serializable generate(SessionImplementor session, Object obj) throws HibernateException { if (obj == null) throw new HibernateException(new NullPointerException()) ; if ((((EntityWithId) obj).getId()) == null) { Serializable id = super.generate(session, obj) ; return id; } else { return ((EntityWithId) obj).getId(); } }
在这里,你基本上定义了自己的ID生成器(基于Identity策略),如果未设置ID,则将生成委托给默认生成器。
主要缺点是它将你绑定为JPA提供程序的Hibernate …但是它与我的MySQL项目完美配合
另一个实现,方法更简单。
这其中的工作原理与两个基于XML注释或基于配置:它依靠hibernate元数据中获取价值为对象的ID。根据你的配置替换SequenceGenerator为IdentityGenerator(或任何其他生成器)。(创建装饰器而不是子类,将装饰的ID生成器作为参数传递给此生成器,作为练习留给读者)。
SequenceGenerator
IdentityGenerator
public class UseExistingOrGenerateIdGenerator extends SequenceGenerator { @Override public Serializable generate(SessionImplementor session, Object object) throws HibernateException { Serializable id = session.getEntityPersister(null, object) .getClassMetadata().getIdentifier(object, session); return id != null ? id : super.generate(session, object); } }
练习的答案(根据要求使用装饰器模式),未经过实际测试:
public class UseExistingOrGenerateIdGenerator implements IdentifierGenerator, Configurable { private IdentifierGenerator defaultGenerator; @Override public void configure(Type type, Properties params, Dialect d) throws MappingException; // For example: take a class name and create an instance this.defaultGenerator = buildGeneratorFromParams( params.getProperty("default")); } @Override public Serializable generate(SessionImplementor session, Object object) throws HibernateException { Serializable id = session.getEntityPersister(null, object) .getClassMetadata().getIdentifier(object, session); return id != null ? id : defaultGenerator.generate(session, object); } }