Cascade Save for spring mongo data

1. we have some entities like below:

    AlarmLogs.java

package com.eifesun.monitor.web.model;

import static com.eifesun.monitor.DeviceType.fromValue;
import static com.eifesun.monitor.inverter.power20k.ErrorCode.getType;
import static org.joda.time.DateTime.now;

import java.util.Date;

import org.bson.types.ObjectId;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.PeriodType;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Transient;
import org.springframework.data.annotation.Version;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;

import com.eifesun.monitor.DeviceType;
import com.eifesun.monitor.util.Helper;
import com.eifesun.monitor.web.model.mongodb.CascadeSave;

@Document(collection = "alarm_logs")
public class AlarmLogs {
    @Id
    private ObjectId id;
    @Version
    private Long version;
    @DateTimeFormat(iso = ISO.DATE_TIME)
    private Date alarmDate;
    private String deviceType;
    private String clientId;
    private String errorType;
    private int errorValue;

    @CreatedDate
    private DateTime createdDate;
    @LastModifiedDate
    private DateTime lastModifiedDate;

    @DBRef
    @CascadeSave
    private AlarmDetails alarmDetails;

    @Transient
    private static final String DATE_PARTEN = "MM/dd/yyyy HH:mm";

    public AlarmLogs() {
    }

    public AlarmLogs(DeviceType deviceType, String clientId, String errorType, int errorValue) {
        this.deviceType = deviceType.toValue();
        this.clientId = clientId;
        this.errorType = errorType;
        this.errorValue = errorValue;
        this.alarmDate = now().toDate();
    }

    public String getCreatedDate() {
        return createdDate.toString(DATE_PARTEN);
    }

    public String getAlarmRemainedTime() {
        Interval interval = new Interval(createdDate.getMillis(), createdDate.getMillis());
        DateTime start = this.version > 0 ? lastModifiedDate : now();
        interval.withEndMillis(start.getMillis());
        return Helper.FORMATTER.print(interval.toPeriod(PeriodType.yearMonthDayTime()));
    }

    public ObjectId getId() {
        return id;
    }

    public String getDeviceType() {
        return fromValue(deviceType).toDisplay();
    }

    public String getErrorMessage() {
        return getType(errorType).getDescription(errorValue);
    }

    public String getErrorType() {
        return errorType;
    }

    public int getErrorValue() {
        return errorValue;
    }

    public String getClientId() {
        return clientId;
    }

    public AlarmDetails getAlarmDetails() {
        return alarmDetails;
    }

    public void setAlarmDetails(AlarmDetails alarmDetails) {
        this.alarmDetails = alarmDetails;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public DateTime getLastModifiedDate() {
        return lastModifiedDate;
    }

}

   AlarmDetails.java

package com.eifesun.monitor.web.model;

import org.bson.types.ObjectId;
import org.joda.time.DateTime;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "alarm_details")
public class AlarmDetails {
    @Id
    private ObjectId id;
    private int panel1Power;
    private int panel2Power;
    private int panel1Current;
    private int panel2Current;
    private int panel1Voltage;
    private int panel2Voltage;
    private int outputPower;
    private int lineRAC;
    private int lineRV;
    private int lineSAC;
    private int lineSV;
    private int lineTAC;
    private int lineTV;
    private int gridFrequence;
    private int statusCode;
    private int boxTemperature;
    private int igbtTemperature;
    private int workingHour;
    @CreatedDate
    protected DateTime createdDate;

    public AlarmDetails() {
    }

    public int getPanel1Power() {
        return panel1Power;
    }

    public void setPanel1Power(int panel1Power) {
        this.panel1Power = panel1Power;
    }

    public int getPanel2Power() {
        return panel2Power;
    }

    public void setPanel2Power(int panel2Power) {
        this.panel2Power = panel2Power;
    }

    public int getPanel1Current() {
        return panel1Current;
    }

    public void setPanel1Current(int panel1Current) {
        this.panel1Current = panel1Current;
    }

    public int getPanel2Current() {
        return panel2Current;
    }

    public void setPanel2Current(int panel2Current) {
        this.panel2Current = panel2Current;
    }

    public int getPanel1Voltage() {
        return panel1Voltage;
    }

    public void setPanel1Voltage(int panel1Voltage) {
        this.panel1Voltage = panel1Voltage;
    }

    public int getPanel2Voltage() {
        return panel2Voltage;
    }

    public void setPanel2Voltage(int panel2Voltage) {
        this.panel2Voltage = panel2Voltage;
    }

    public int getOutputPower() {
        return outputPower;
    }

    public void setOutputPower(int outputPower) {
        this.outputPower = outputPower;
    }

    public int getLineRAC() {
        return lineRAC;
    }

    public void setLineRAC(int lineRAC) {
        this.lineRAC = lineRAC;
    }

    public int getLineRV() {
        return lineRV;
    }

    public void setLineRV(int lineRV) {
        this.lineRV = lineRV;
    }

    public int getLineSAC() {
        return lineSAC;
    }

    public void setLineSAC(int lineSAC) {
        this.lineSAC = lineSAC;
    }

    public int getLineSV() {
        return lineSV;
    }

    public void setLineSV(int lineSV) {
        this.lineSV = lineSV;
    }

    public int getLineTAC() {
        return lineTAC;
    }

    public void setLineTAC(int lineTAC) {
        this.lineTAC = lineTAC;
    }

    public int getLineTV() {
        return lineTV;
    }

    public void setLineTV(int lineTV) {
        this.lineTV = lineTV;
    }

    public int getGridFrequence() {
        return gridFrequence;
    }

    public void setGridFrequence(int gridFrequence) {
        this.gridFrequence = gridFrequence;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public int getBoxTemperature() {
        return boxTemperature;
    }

    public void setBoxTemperature(int boxTemperature) {
        this.boxTemperature = boxTemperature;
    }

    public int getIgbtTemperature() {
        return igbtTemperature;
    }

    public void setIgbtTemperature(int igbtTemperature) {
        this.igbtTemperature = igbtTemperature;
    }

    public int getWorkingHour() {
        return workingHour;
    }

    public void setWorkingHour(int workingHour) {
        this.workingHour = workingHour;
    }

}

2. here we create a new annotation "CascadeSave" on fields "alarmDetails".

package com.eifesun.monitor.web.model.mongodb;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CascadeSave {

}

 

  CascadingMongoEventListener.java

package com.eifesun.monitor.web.model.mongodb;

import java.lang.reflect.Field;

import javax.inject.Inject;

import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.util.ReflectionUtils;

@SuppressWarnings("rawtypes")
public class CascadingMongoEventListener extends AbstractMongoEventListener {
    @Inject
    private MongoOperations mongoOperations;

    @Override
    public void onBeforeConvert(final Object source) {
        ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {

            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                ReflectionUtils.makeAccessible(field);

                if (field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)) {
                    final Object fieldValue = field.get(source);
                    if (fieldValue == null) {
                        return;
                    }

                    DbRefFieldCallback callback = new DbRefFieldCallback();
                    ReflectionUtils.doWithFields(fieldValue.getClass(), callback);
                    if (!callback.isIdFound()) {
                        throw new MappingException("Cannot perform cascade save on child object without id set");
                    }

                    mongoOperations.save(fieldValue);
                }
            }
        });
    }

    private static class DbRefFieldCallback implements ReflectionUtils.FieldCallback {
        private boolean idFound;

        public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
            ReflectionUtils.makeAccessible(field);

            if (field.isAnnotationPresent(Id.class)) {
                idFound = true;
            }
        }

        public boolean isIdFound() {
            return idFound;
        }
    }
}

 

猜你喜欢

转载自sunxboy.iteye.com/blog/2035760