在Hibernate中绕过GeneratedValue(合并数据不在db?中)

Jan*_*Jan 37 java orm spring hibernate jpa

我的问题与[1][2]中描述的相同.我需要手动设置默认的自动生成值(为什么?导入旧数据).如[1]中所述,使用Hibernate entity = em.merge(entity)将会起到作用.

不幸的是,它没有.我既没有得到错误也没有任何其他警告.该实体不会出现在数据库中.我正在使用Spring和Hibernate EntityManager 3.5.3-Final.

有任何想法吗?

Lau*_*ire 49

另一种实现方式更简单.

这其中的工作原理与两个基于XML注释或基于配置:它依靠休眠元数据中获取价值为对象的ID.更换SequenceGeneratorIdentityGenerator因您的配置(或任何其他发电机).(创建装饰器而不是子类化,将装饰的ID生成器作为参数传递给此生成器,留给读者练习).

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

回答练习(使用装饰器模式,按要求),未经过实际测试:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如何在@GeneratedValue中使用它? (4认同)
  • 感谢您的帮助,它在5.2中并不适合我,但它的核心是黄金!我为hibernate 5.2更新了它:/sf/answers/3417336891/ (3认同)
  • 我在Hibernate的JIRA中添加了一个缺陷.请投票:https://hibernate.atlassian.net/browse/HHH-10429 (2认同)

Kev*_*vin 45

它适用于我的项目,代码如下:

@XmlAttribute
@Id
@Basic(optional = false)
@GeneratedValue(strategy=GenerationType.IDENTITY, generator="IdOrGenerated")
@GenericGenerator(name="IdOrGenerated",
                  strategy="....UseIdOrGenerate"
)
@Column(name = "ID", nullable = false)
private Integer id;
Run Code Online (Sandbox Code Playgroud)

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

    }
}
Run Code Online (Sandbox Code Playgroud)

您基本上定义了自己的ID生成器(基于Identity策略),如果未设置ID,则将生成委派给默认生成器.

主要的缺点是它将你作为JPA提供程序绑定到Hibernate ...但它与我的MySQL项目完美配合

  • 我试过这个,但我一直得到:"字段'id'没有默认值" (2认同)
  • @lior,需要使用继承自IdentityGenerator的IncrementGenerator。 (2认同)
  • 在我提出一个新问题之前,我想通过要求你为Hibernate 5提供一个解决方案来提供更多点的机会,这个解决方案将`IdentityGenerator`的接口改为`InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(PostInsertIdentityPersister,Dialect,boolean)`. (2认同)

Cad*_*sto 17

更新LaurentGrégoire对hibernate 5.2的回答,因为它似乎有所改变.

public class UseExistingIdOtherwiseGenerateUsingIdentity extends IdentityGenerator {

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        Serializable id = session.getEntityPersister(null, object).getClassMetadata().getIdentifier(object, session);
        return id != null ? id : super.generate(session, object);
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:(替换包名)

@Id
@GenericGenerator(name = "UseExistingIdOtherwiseGenerateUsingIdentity", strategy = "{package}.UseExistingIdOtherwiseGenerateUsingIdentity")
@GeneratedValue(generator = "UseExistingIdOtherwiseGenerateUsingIdentity")
@Column(unique = true, nullable = false)
protected Integer id;
Run Code Online (Sandbox Code Playgroud)


小智 6

我在这里给出了一个对我有用的解决方案:
创建自己的识别器/序列生成器

public class FilterIdentifierGenerator extends IdentityGenerator implements IdentifierGenerator{

@Override
public Serializable generate(SessionImplementor session, Object object)
        throws HibernateException {
    // TODO Auto-generated method stub
    Serializable id = session.getEntityPersister(null, object)
            .getClassMetadata().getIdentifier(object, session);
    return id != null ? id : super.generate(session, object);
}

}
Run Code Online (Sandbox Code Playgroud)

将您的实体修改为:

@Id
@GeneratedValue(generator="myGenerator")
@GenericGenerator(name="myGenerator", strategy="package.FilterIdentifierGenerator")
@Column(unique=true, nullable=false)
private int id;
...
Run Code Online (Sandbox Code Playgroud)

而保存而不是persist()使用merge()update()


for*_*has 5

如果您使用休眠模式org.hibernate.id.UUIDGenerator生成String ID,建议您使用:

public class UseIdOrGenerate extends UUIDGenerator {


    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        Serializable id = session.getEntityPersister(null, object).getClassMetadata().getIdentifier(object, session);
        return id != null ? id : super.generate(session, object);
    }
}
Run Code Online (Sandbox Code Playgroud)