@SuppressWarnings("unchecked")
 private <T> void visit(JsonReadBeanVisitor<T> beanVisitor) {
   // listen for property change events so that
   // we can update the loadedProps if necessary
   if (ebi != null) {
     ebi.addPropertyChangeListener(this);
   }
   beanVisitor.visit((T) bean, unmapped);
   if (ebi != null) {
     ebi.removePropertyChangeListener(this);
   }
 }
  @SuppressWarnings("unchecked")
  public PersistRequestBean(
      SpiEbeanServer server,
      T bean,
      Object parentBean,
      BeanManager<T> mgr,
      SpiTransaction t,
      PersistExecute persistExecute) {

    super(server, t, persistExecute);
    this.beanManager = mgr;
    this.beanDescriptor = mgr.getBeanDescriptor();
    this.beanPersistListener = beanDescriptor.getPersistListener();
    this.bean = bean;
    this.parentBean = parentBean;

    this.controller = beanDescriptor.getPersistController();
    this.concurrencyMode = beanDescriptor.getConcurrencyMode();

    if (bean instanceof EntityBean) {
      this.intercept = ((EntityBean) bean)._ebean_getIntercept();
      if (intercept.isReference()) {
        // allowed to delete reference objects
        // with no concurrency checking
        this.concurrencyMode = ConcurrencyMode.NONE;
      }
      // this is ok to not use isNewOrDirty() as used for updates only
      this.isDirty = intercept.isDirty();
      if (!isDirty) {
        this.changedProps = intercept.getChangedProps();
      } else {
        // merge changed properties on the bean with changed embedded beans
        Set<String> beanChangedProps = intercept.getChangedProps();
        Set<String> dirtyEmbedded = beanDescriptor.getDirtyEmbeddedProperties(bean);
        this.changedProps = mergeChangedProperties(beanChangedProps, dirtyEmbedded);
      }
      this.loadedProps = intercept.getLoadedProps();
      this.oldValues = (T) intercept.getOldValues();
      this.vanilla = false;

    } else {
      // have to assume the vanilla bean is dirty
      this.vanilla = true;
      this.isDirty = true;
      this.loadedProps = null;
      this.changedProps = null;
      this.intercept = null;

      // degrade concurrency checking to none for vanilla bean
      if (concurrencyMode.equals(ConcurrencyMode.ALL)) {
        this.concurrencyMode = ConcurrencyMode.NONE;
      }
    }
  }
  /** Post processing. */
  public void postExecute() throws SQLException {

    if (controller != null) {
      controllerPost();
    }

    if (intercept != null) {
      // if bean persisted again then should result in an update
      intercept.setLoaded();
    }

    addEvent();

    if (isLogSummary()) {
      logSummary();
    }
  }
 /**
  * Set loaded properties when generated values has added properties such as created and updated
  * timestamps.
  */
 public void setLoadedProps(Set<String> additionalProps) {
   if (intercept != null) {
     intercept.setLoadedProps(additionalProps);
   }
 }