programing

최대 절전 모드에서 생성된 값 무시(데이터 병합이 DB에 없습니까?)

cafebook 2023. 8. 11. 22:34
반응형

최대 절전 모드에서 생성된 값 무시(데이터 병합이 DB에 없습니까?)

제 문제는 [1] 또는 [2]에서 설명한 것과 같습니다.기본적으로 자동 생성 값을 수동으로 설정해야 합니다(이전 데이터 가져오기 이유).[1]에서 설명한 바와 같이 Hibernate의entity = em.merge(entity)할 수 있을 겁니다

불행하게도 저에게는 그렇지 않습니다.저는 오류나 다른 경고를 받지 않습니다.엔티티는 데이터베이스에 나타나지 않습니다.Spring and Hibernate Entity Manager 3.5.3-Final을 사용하고 있습니다.

아이디어 있어요?

또 다른 구현은 훨씬 더 간단합니다.

이 구성은 주석 기반 또는 xml 기반 구성 모두에서 작동합니다. 즉, 개체의 ID 값을 가져오기 위해 최대 절전 모드 메타데이터에 의존합니다.교체하다SequenceGenerator타고IdentityGenerator사용자 구성에 따라 (또는 다른 생성기).(서브클래스 대신 데코레이터를 만들어 장식된 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);
    }
}

실제로 테스트되지 않은 연습(요청에 따라 데코레이터 패턴 사용)에 대한 답변:

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

다음 코드로 제 프로젝트에서 작동합니다.

@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 전략에 따라 기본적으로 자신의 ID 생성기를 정의하고 ID가 설정되지 않은 경우 생성을 기본 생성기에 위임합니다.

가장 큰 단점은 JPA 공급자로서 최대 절전 모드로 제한된다는 것입니다... 그러나 MySQL 프로젝트와 완벽하게 작동합니다.

동면 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);
    }
}

다음과 같이 사용합니다. (패키지 이름 바꾸기)

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

최대 절전 모드를 사용하는 경우org.hibernate.id.UUIDGeneratorString 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);
    }
}

저는 여기서 저에게 효과적인 해결책을 제시하고 있습니다.
고유한 식별자 생성기/시퀀스 생성기 생성

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

}

엔티티를 다음과 같이 수정합니다.

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

사용하는 대신 저장하는 동안persist()사용하다merge()또는update()

최대 절전 모드 포럼에서 새 ID 스레드 생성을 선택적으로 비활성화합니다.merge()솔루션이 아닐 수도 있고(적어도 혼자가 아님) 사용자 지정 생성기를 사용해야 할 수도 있습니다(이것이 두 번째 링크임).

제가 직접 테스트하지 않아서 확인할 수 없지만 휴면 상태 포럼의 스레드를 읽는 것을 추천합니다.

이 작업을 수행하려는 다른 사용자에게는 위와 같은 작업이 잘 수행됩니다.각 Entity 클래스(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 object)
            throws HibernateException {
        if (object == null)
            throw new HibernateException(new NullPointerException());

        for (Field field : object.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Id.class)
                    && field.isAnnotationPresent(GeneratedValue.class)) {
                boolean isAccessible = field.isAccessible();
                try {
                    field.setAccessible(true);
                    Object obj = field.get(object);
                    field.setAccessible(isAccessible);
                    if (obj != null) {
                        if (Integer.class.isAssignableFrom(obj.getClass())) {
                            if (((Integer) obj) > 0) {
                                return (Serializable) obj;
                            }
                        }
                    }
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return super.generate(session, object);
    }
}

실행 중인 트랜잭션이 필요합니다.

트랜잭션이 수동으로 관리되는 경우:

entityManager.getTransaction().begin();

(물론 약속하는 것을 잊지 마세요)

선언형 트랜잭션을 사용하는 경우 적절한 선언을 사용합니다(주석을 통해 가능성이 높음).

모드 을 " " " " " " " 으로 debug(log4j.logger.org.hibernate=debug자세한 내용을 추적하려면 log4j.properties에서 를 클릭합니다.

언급URL : https://stackoverflow.com/questions/3194721/bypass-generatedvalue-in-hibernate-merge-data-not-in-db

반응형