2017-05-22 64 views
3

我正在使用xodus數據庫,並且我想將java.time.Instant作爲我的模型對象(Diary)的屬性進行存儲,所以我實現了InstantBinding如何將自定義屬性類型註冊到xodus`PersistentEntityStore`

下一頁在庫對象,我創建了我的Diary對象我在保存註冊InstantBindig和資源庫,因爲PersistentEntityStore.registerCustomPropertyType(@NotNull final StoreTransaction txn, @NotNull final Class<? extends Comparable> clazz,@NotNull final ComparableBinding binding);需求StoreTransaction txn輸入負載的方法來工作。 然後當我使用的倉庫,我得到這個異常:

Exception in thread "JavaFX Application Thread" jetbrains.exodus.entitystore.EntityStoreException: Already registered property type id 9 
at jetbrains.exodus.entitystore.tables.PropertyTypes.registerCustomPropertyType(PropertyTypes.java:77) 
at jetbrains.exodus.entitystore.PersistentEntityStoreImpl.registerCustomPropertyType(PersistentEntityStoreImpl.java:520) 
at io.github.mojtab23.diaries.DiaryRepository.lambda$saveDiary$0(DiaryRepository.java:35) 
at jetbrains.exodus.entitystore.PersistentEntityStoreImpl.executeInTransaction(PersistentEntityStoreImpl.java:529) 
at io.github.mojtab23.diaries.DiaryRepository.saveDiary(DiaryRepository.java:34) 
at io.github.mojtab23.diaries.DiariesView.saveChanges(DiariesView.java:222) 
at io.github.mojtab23.diaries.DiariesView.lambda$buildDiaryEditor$6(DiariesView.java:203) 
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49) 
at javafx.event.Event.fireEvent(Event.java:198) 
at javafx.scene.Node.fireEvent(Node.java:8413) 
at javafx.scene.control.Button.fire(Button.java:185) 
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182) 
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96) 
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) 
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) 
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) 
at javafx.event.Event.fireEvent(Event.java:198) 
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757) 
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) 
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) 
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417) 
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416) 
at com.sun.glass.ui.View.handleMouseEvent(View.java:555) 
at com.sun.glass.ui.View.notifyMouse(View.java:937) 
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) 
at java.lang.Thread.run(Thread.java:745) 

那麼,什麼是註冊自定義屬性類型xodus的正確方法嗎?

這裏是我的課:

日記

import javafx.beans.property.ObjectProperty; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import jetbrains.exodus.entitystore.EntityId; 

public class Diary implements Cloneable { 

private final ObjectProperty<Instant> timestamp; 
private final StringProperty text; 
private EntityId id; 

public Diary() { 
    this.text = new SimpleStringProperty(); 
    timestamp = new SimpleObjectProperty<>(Instant.now()); 
} 

public Diary(String text, Instant time) { 
    this.text = new SimpleStringProperty(text); 
    timestamp = new SimpleObjectProperty<>(time); 

} 

public Diary(SimpleObjectProperty<Instant> timestamp, StringProperty text, EntityId id) { 
    this.timestamp = timestamp; 
    this.text = text; 
    this.id = id; 
} 

public EntityId getId() { 
    return id; 
} 

public void setId(EntityId id) { 
    this.id = id; 
} 

public Instant getTimestamp() { 
    return timestamp.get(); 
} 

public void setTimestamp(Instant timestamp) { 
    this.timestamp.set(timestamp); 
} 

public ObjectProperty<Instant> timestampProperty() { 
    return timestamp; 
} 

public String getText() { 
    return text.get(); 
} 

public void setText(String text) { 
    this.text.set(text); 
} 

public StringProperty textProperty() { 
    return text; 
} 

@Override 
public String toString() { 
    return "Diary{" + 
      "id=" + id + 
      ", timestamp=" + timestamp + 
      ", text=" + text + 
      '}'; 
} 

@Override 
public Object clone() throws CloneNotSupportedException { 
    return super.clone(); 
} 
} 

DiaryRepository:

import io.github.mojtab23.diaries.model.diary.Diary; 
import jetbrains.exodus.entitystore.*; 
import org.jetbrains.annotations.Nullable; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.stereotype.Repository; 

import javax.annotation.PreDestroy; 
import java.time.Instant; 
import java.util.ArrayList; 
import java.util.List; 



@Repository 
public class DiaryRepository { 
    private static final Logger LOGGER = LoggerFactory.getLogger(DiaryRepository.class); 

    private final PersistentEntityStore entityStore; 
    private final String entityType = "Diary"; 

    public DiaryRepository() { 
     entityStore = PersistentEntityStores.newInstance(".DiariesAppData"); 


    } 


    public void saveDiary(final Diary diary) { 
     entityStore.executeInTransaction((StoreTransaction txn) -> { 
      entityStore.registerCustomPropertyType(txn, Instant.class, InstantBinding.BINDING); 

      diaryToEntity(diary, txn); 
     }); 

    } 

    public Entity diaryToEntity(final Diary diary, final StoreTransaction txn) { 

     final Entity diaryEntity = txn.newEntity(entityType); 
     diaryEntity.setProperty("text", diary.getText()); 

     diaryEntity.setProperty("timestamp", diary.getTimestamp()); 
     return diaryEntity; 
    } 


    public Diary entityToDiary(final Entity entity, final StoreTransaction txn) { 


     final @Nullable String text = (String) entity.getProperty("text"); 
     final @Nullable Instant timestamp = (Instant) entity.getProperty("timestamp"); 

     if (text != null) { 
      if (timestamp != null) { 
        return new Diary(text, timestamp); 
      } else 
       return new Diary(text, Instant.MIN); 
     } 
     return null; 
    } 

    public List<Diary> readAllDiaries() { 

     return entityStore.computeInReadonlyTransaction(txn -> { 
      entityStore.registerCustomPropertyType(txn, Instant.class, InstantBinding.BINDING); 

      final EntityIterable allDiaries = txn.getAll(entityType); 
       final List<Diary> diaryList = new ArrayList<>(); 
      allDiaries.forEach(entity -> { 
       final Diary e = entityToDiary(entity, txn); 
       if (e != null) { 
        diaryList.add(e); 
       } 
      }); 
      LOGGER.warn("Number of Diaries: " + diaryList.size()); 
      return diaryList; 

     }); 

    } 

    public void deleteAll() { 

     entityStore.executeInTransaction(txn -> { 


      txn.getAll(entityType).forEach(entity -> 
      { 
       if (!entity.delete()) { 
        LOGGER.warn("cant delete {}", entityToDiary(entity, txn)); 
       } 
      }); 
     }); 

    } 


    @PreDestroy 
    public void atEnd() { 
     entityStore.close(); 
    } 

} 

InstantBinding:

import jetbrains.exodus.ArrayByteIterable; 
import jetbrains.exodus.ByteIterable; 
import jetbrains.exodus.bindings.BindingUtils; 
import jetbrains.exodus.bindings.ComparableBinding; 
import jetbrains.exodus.util.LightOutputStream; 
import org.jetbrains.annotations.NotNull; 

import java.io.ByteArrayInputStream; 
import java.time.Instant; 

    public class InstantBinding extends ComparableBinding { 

    public static final InstantBinding BINDING = new InstantBinding(); 

    public static Instant entryToInstant(@NotNull final ByteIterable entry) { 
     return (Instant) BINDING.entryToObject(entry); 
    } 

    public static ArrayByteIterable instantToEntry(final Instant object) { 
     return BINDING.objectToEntry(object); 
    } 

    @Override 
    public Comparable readObject(@NotNull ByteArrayInputStream stream) { 
     final long l = BindingUtils.readLong(stream); 
     final int i = BindingUtils.readInt(stream); 
     return Instant.ofEpochSecond(l, i); 
    } 

    @Override 
    public void writeObject(@NotNull LightOutputStream output, @NotNull Comparable object) { 
     final Instant instant = (Instant) object; 
     output.writeUnsignedLong(instant.getEpochSecond()^0x8000000000000000L); 
     output.writeUnsignedInt(instant.getNano()^0x80000000); 

    } 

} 
+0

'DiariesView#saveChanges()'創建一個事務嗎? –

+0

@ vyacheslav-lukianov transacction將在'DiaryRepository.saveDiary'方法中創建。 我不知道爲什麼'registerCustomPropertyType'需要事務作爲參數?! – mojtab23

回答

1

看來你正在經歷this bug。它已經修復,該修補程序將在1.0.6版本中提供。目前有兩種解決方法:

  1. 環繞的PersistentEntityStore.registerCustomPropertyType()調用與try-catch塊,趕上EntityStoreException和忽略它。當下一個版本(1.0.6)可用時,使您的項目取決於它,並刪除try-catch塊。
  2. 根據發佈到Sonartype snapshots repository1.0.6-SNAPSHOT版本設置您的項目。
相關問題