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