일간 에러 2021-11-12

작성: 2021.11.12

수정: 2021.11.12

읽는시간: 00 분

Development/Daily Error

반응형

save(object) 메서드 먹통

문제

dao.save(object)를 아무리 호출해도 저장이 되지 않아 테스트 케이스를 통과 하지 못하던 에러.

저장만 안되고, 기존에 이미 있던 DB를 조회 하거나 수정 하는데는 문제가 없어서 당황스러웠다.

원인

Spring Data JPA를 사용할때는 save 메서드를 당연하게 사용했는데, 이번에는 다중 쓰레드에서의 DB 커넥션을 관리해줘야 하는 상황이다 보니, Hibernate가 제공하는게 아닌 다른 구현체를 상속해서 데이터 접근 객체를 만들어 사용하고 있었다.

하다 하다 안되어서 메서드 목록을 보니 create 메서드가 따로 있기에, 그럼 save와 어떤 식으로 차이가 있는지 살펴보려고 코드를 타고 들어가니..

public abstract class AbstractHibernateDAO<T> implements GenericDAO<T> {

    protected AbstractHibernateDAO() {

    }

    @Override
    public T create(Context context, T t) {
        getHibernateSession(context).persist(t);
        return t;
    }

    @Override
    public void save(Context context, T t) {
        // Isn't required, is just here for other DB implementation. Hibernate auto
        // keeps track of changes.
    }

왠걸 애초에 구현되어 있지 않았다.

사실 오래전에 똑같은 문제로 잠깐 막힌 적이 있긴 했는데.. 그때는 그냥 save를 create로 바꿔 쓰는걸로 넘겼었다.

그래도 또 같은 문제로 혼동이 생기니 그대로 두면 안되겠다는 생각이 들었다.

해결

save 메서드에 내용을 채워 넣을 수도 있지만, 코드 작성자의 의도가 어쨌든 Hiabernate의 변경감지를 사용해서 영속성 컨텍스트의 종료 시점에 변경된 내용들이 자동으로 업데이트 되는 것을 원했기 때문에 의도대로 save를 못쓰게 알려서 혼동을 줄이기로 결정.

image-20211112144146196

@Depreciated 걸어 주고, 간단하게 주석을 달아 주었다.

image-20211112144352397

어쨌든 이제 사용하려고 하면 한번 줄이 그어졌기 때문에 최소한 사용하기 전에 의심을 할 수 있다.

그러고 나서 편하게 이제 create 메서드 만을 사용하면 된다.

Error attempting to apply AttributeConverter

문제

특정 날짜를 기준으로 데이터를 긁어오는 쿼리를 생성 중, AttributeConverter 에러가 났다.

org.springframework.orm.jpa.JpaSystemException: Error attempting to apply AttributeConverter; nested exception is javax.persistence.PersistenceException: Error attempting to apply AttributeConverter at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:418)

원인

사실 다행히도 AttributeConverter 는 내가 얼마전에 추가한 코드 하나 뿐이기 때문에 어렵지 않게 원인을 찾을 수 있었다.

진행중인 프로젝트에서 사용중인 JPA의 버전이 JAVA8 이전에 나온 2.1버전 이다보니 LocalDateTime를 사용하지 못해 날짜 계산에 불편함을 겪고 있었는데, 그 문제를 해결하기 위해 얼마전에 컨버터를 추가해서 편하게 LocalDateTime을 사용 하고 있었던 상황.

혹시 저처럼 JPA 버전이 낮아 LocalDateTime을 사용하지 못하고 있는 분이 있다면 꼭 컨버터를 만들어서 사용해 보시길 추천합니다. 매우 간단하게 Entity 객체에서도 LocalDateTime 프로퍼티를 사용할 수 있게 됩니다.

다만, 위의 컨버터는 DB와의 관계에서 작동하며, json으로 직렬화 되어 나갈때 또 다시 LocalDateTime 이 parsing 되지 않아 또 다른 오류가 날 수 있습니다. 그럴때는 DTO에서는 Date를 쓰거나, 혹은 jackson 라이브러리를 추가 해서 사용하세요.

compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.4")



@Converter(autoApply = true)
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {

    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime locDateTime) {
        return (locDateTime == null ? null : Timestamp.valueOf(locDateTime));
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
        return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
    }
}

LocalDateTime을 사용하기 위해 추가 해 둔 @Converter

이렇게 컨버터를 만들어서 사용하고 있음에도 습관처럼, 예전에 만들어 둔 유틸 메서드를 이용해서 LocalDateTime를 Date로 변환해서 parameter를 추가 하고 있었다. LocalDateTime 에서 Date로 변환되어 넘어 온 파라미터를 LocalDateTime이 넘어왔다고 가정하고 Timestamp로 변환하려 하고 있었으니 컨버터가 정상적으로 작동 하지 못하던 상황.

query.add(Restrictions.lt("createdDate", Tools.convertLocalDateTimeToDate(date)));

해결

Date로 변환하지 말고, LocalDateTime 받아온 그대로 파라미터를 넘겨 주니 문제가 해결되었다.

public List<Data> findByCreatedDateBefore(Context context, LocalDateTime date) {
    Criteria query = createCriteria(context, Data.class);
    query.add(Restrictions.lt("createdDate", date));
    return list(query);
}

error code received from iRODS:-345000

SessionClosingIRODSFileOutputStream - rethrowing JargonException as IO exception for write operation
org.irods.jargon.core.exception.JargonException: error code received from iRODS:-345000
at org.irods.jargon.core.connection.IRODSErrorScanner.checkSpecificCodesAndThrowIfExceptionLocated(IRODSErrorScanner.java:325)

문제

iRODS 파일을 받아오기 위해 열었던 인풋 스트림을 닫으려고 할 때 iRODS:-345000 에러 발생.

원인

try with resources 구문을 이용해 openBitstream 으로 bitStreamZip의 인풋 스트림을 연 상태에서 해당 파일을 삭제 하니, 스트림을 닫을 때 문제가 발생했었음. 스트림이 열려있는 파일을 삭제해버리니 어찌 보면 당연

iRODS:-345000 는 멀티 쓰레드 접근 시도에 관련된 에러 인 듯 하지만 후에 같은 에러가 발생한다면 지금의 경험을 참고 해야 할듯.

해결

try 블럭이 완전히 닫히고 나서 iRods에 해당 파일을 삭제하는 명령을 보내도록 순서를 조절 해 주니 문제 없이 작동.



image-20211112150300815

image-20211112170232301

오늘의 문제 해결 끝.

반응형