gpt4 book ai didi

hibernate - 在 embeddable/embedded-id 中使用 hibernate 序列生成器

转载 作者:行者123 更新时间:2023-12-03 21:36:18 24 4
gpt4 key购买 nike

在 Hibernate 中,是否可以将@GeneratedValue 和@SequenceGenerator 与@EmbeddedId 或@Embeddable 一起使用?

我需要一个用于嵌入 ID(或 @embeddable)的字符串序列生成器。

最佳答案

我在我的项目中使用它,到目前为止它非常令人满意,零序列。它使用“select max(id) + 1”。适用于单键或复合键:

可识别.java

package my.app.hibernate;

import java.io.Serializable;

public interface Identifiable<T extends Serializable> {
T getId();
}

复合键实体.java
 package my.app.hibernate;

import java.io.Serializable;

public interface CompositeKeyEntity<T extends Serializable> extends Identifiable<T> {
}

单键实体.java
package my.app.hibernate;

import java.io.Serializable;

public interface SingleKeyEntity<T extends Serializable> extends Identifiable<T> {
}

AssignedIdentityGenerator.java
package my.app.hibernate;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.internal.CriteriaImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.util.FieldUtils;

public class AssignedIdentityGenerator extends IdentityGenerator {
private static final String ID_FIELD_NAME = "id";
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
private Field sequenceField;
private String entityClassName;

@Override
public Serializable generate(SessionImplementor session, Object obj) {
@SuppressWarnings("unchecked")
Identifiable<Serializable> identifiable = (Identifiable<Serializable>)obj;

entityClassName = obj.getClass().getName();
Criteria criteria = new CriteriaImpl(entityClassName, session);
criteria.setReadOnly(true);
Object toSet = null;

if (identifiable instanceof CompositeKeyEntity) {
Serializable id = identifiable.getId();
if (id != null) {
String embaddebleClassName = id.getClass().getName();
buildCriteriaForEmbeddedId(id, embaddebleClassName, criteria);
toSet = id;
}
} else if (obj instanceof SingleKeyEntity) {
toSet = identifiable;
sequenceField = FieldUtils.getField(identifiable.getClass(), ID_FIELD_NAME);
buildCriteriaForSingleId(criteria);
}

Number one = castToSequenceNumberType(1L);
Number value = (Number) criteria.uniqueResult();

if(value != null) {
value = castToSequenceNumberType(value.longValue() + one.longValue());

setFieldValue(sequenceField, value, toSet);
} else {
value = one;
setFieldValue(sequenceField, value, toSet);
}

return identifiable.getId();
}

private void buildCriteriaForSingleId(Criteria criteria) {
criteria.setProjection(Projections.max(ID_FIELD_NAME).as("seq"));
}

private void buildCriteriaForEmbeddedId(Serializable id, String embaddebleClassName, Criteria criteria) {
List<Field> fields = Arrays.asList(id.getClass().getDeclaredFields());

class Utils {
Field field;
boolean numberFound = false;
}
final Utils utils = new Utils();

for (Field field : fields) {
if ("serialVersionUID".equals(field.getName()) || "$jacocoData".equals(field.getName())) {
continue;
}

if (Number.class.isAssignableFrom(field.getType())) {
if (utils.numberFound) {
throw new IllegalArgumentException(
embaddebleClassName + " has more then one sequence field: " + field.getName() + ", "
+ utils.field.getName() + ",...");
}

utils.numberFound = true;
utils.field = field;
sequenceField = field;

criteria.setProjection(Projections.max(ID_FIELD_NAME + "." + sequenceField.getName()).as("seq"));
} else {
criteria.add(Restrictions.eq(ID_FIELD_NAME + "." + field.getName(), getFieldValue(field, id)));
}
}
}

private Number castToSequenceNumberType(Number n) {
return (Number) sequenceField.getType().cast(n);
}

private void setFieldValue(Field field, Object value, Object to) {
try {
field.setAccessible(true);
field.set(to, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
LOG.error(e.getMessage(), e);
}
}

private Object getFieldValue(Field field, Object from) {
try {
field.setAccessible(true);
return field.get(from);
} catch (IllegalArgumentException | IllegalAccessException e) {
LOG.error(e.getMessage(), e);
}

return null;
}
}

客户.java
package my.app.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;

import my.app.hibernate.SingleKeyEntity;

@Entity(name = "whatever_entity_name")
@GenericGenerator(name = "WHATEVER_NAMED_GENERATOR", strategy = "my.app.hibernate.AssignedIdentityGenerator")
public class Customer implements SingleKeyEntity<Long> {

@Id
@GeneratedValue(generator = "WHATEVER_NAMED_GENERATOR")
private Long id;
@Column(nullable = false)
private String name;
}

CustomerItemsId.java(Item.java 省略,因为它遵循 SingleKeyEntity 示例)
package my.app.entities;

import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Embeddable
public class CustomerItemsId implements Serializable {
private static final long serialVersionUID = 1L; //generate one

@ManyToOne
@JoinColumn(name = "customer_id")
private Customer customer;
@ManyToOne
@JoinColumn(name = "item_id")
private Item item;
private Long seq; //name as you wish
}

客户项目.java
package my.app.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;

import my.app.hibernate.CompositeKeyEntity;

@Entity(name = "whatever_entity_name")
@GenericGenerator(name = "WHATEVER_NAMED_GENERATOR", strategy = "my.app.hibernate.AssignedIdentityGenerator")
public class CustomerItems implements CompositeKeyEntity<CustomerItemsId> {

@GeneratedValue(generator = "WHATEVER_NAMED_GENERATOR")
private CustomerItems id;
@Column(nullable = false)
private String randomColumn1;
@Column(nullable = false)
private String randomColumn2;
}

关于hibernate - 在 embeddable/embedded-id 中使用 hibernate 序列生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35463473/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com