Bladeren bron

fix没有客观题识别结果的查询排除无客观题科目

xiatian 10 maanden geleden
bovenliggende
commit
c1a734f397

+ 17 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/query/ExamStudentSearchQuery.java

@@ -124,9 +124,12 @@ public class ExamStudentSearchQuery extends BaseQuery<ExamStudent> {
 
     // 不可重复
     private Boolean inspectUnrepeated;
-    
+
     private Boolean objectiveFill;
 
+    // 有客观题的科目
+    private List<String> objectiveCodes;
+
     public ExamStudentSearchQuery() {
         super();
         this.statusSet = new HashSet<>();
@@ -584,13 +587,20 @@ public class ExamStudentSearchQuery extends BaseQuery<ExamStudent> {
         this.trial = trial;
     }
 
-	public Boolean getObjectiveFill() {
-		return objectiveFill;
-	}
+    public Boolean getObjectiveFill() {
+        return objectiveFill;
+    }
 
-	public void setObjectiveFill(Boolean objectiveFill) {
-		this.objectiveFill = objectiveFill;
-	}
+    public void setObjectiveFill(Boolean objectiveFill) {
+        this.objectiveFill = objectiveFill;
+    }
 
+    public List<String> getObjectiveCodes() {
+        return objectiveCodes;
+    }
+
+    public void setObjectiveCodes(List<String> objectiveCodes) {
+        this.objectiveCodes = objectiveCodes;
+    }
 
 }

+ 87 - 35
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamStudentServiceImpl.java

@@ -2,14 +2,26 @@ package cn.com.qmth.stmms.biz.exam.service.impl;
 
 import java.math.BigDecimal;
 import java.text.DecimalFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
-import javax.persistence.criteria.*;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.math.RandomUtils;
@@ -25,12 +37,31 @@ import org.springframework.transaction.annotation.Transactional;
 
 import cn.com.qmth.stmms.biz.common.BaseQueryService;
 import cn.com.qmth.stmms.biz.exam.dao.ExamStudentDao;
-import cn.com.qmth.stmms.biz.exam.model.*;
+import cn.com.qmth.stmms.biz.exam.model.AnswerCard;
+import cn.com.qmth.stmms.biz.exam.model.Exam;
+import cn.com.qmth.stmms.biz.exam.model.ExamPackage;
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
-import cn.com.qmth.stmms.biz.exam.service.*;
+import cn.com.qmth.stmms.biz.exam.service.AnswerCardService;
+import cn.com.qmth.stmms.biz.exam.service.CheckStudentService;
+import cn.com.qmth.stmms.biz.exam.service.ExamPackageService;
+import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
+import cn.com.qmth.stmms.biz.exam.service.ExamService;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
+import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.mark.dao.HeaderTagDao;
 import cn.com.qmth.stmms.biz.mark.dao.HeaderTrackDao;
-import cn.com.qmth.stmms.biz.mark.model.*;
+import cn.com.qmth.stmms.biz.mark.model.HeaderTag;
+import cn.com.qmth.stmms.biz.mark.model.HeaderTrack;
+import cn.com.qmth.stmms.biz.mark.model.MarkConfigItem;
+import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
+import cn.com.qmth.stmms.biz.mark.model.MarkSpecialTag;
+import cn.com.qmth.stmms.biz.mark.model.MarkTrack;
+import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
 import cn.com.qmth.stmms.biz.mark.service.MarkSpecialTagService;
 import cn.com.qmth.stmms.biz.mark.service.MarkTrackService;
@@ -43,7 +74,10 @@ import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
 @Service
 public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implements ExamStudentService {
-	private static String[] objectiveAnswer=new String[] {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","?"};
+
+    private static String[] objectiveAnswer = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
+            "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "?" };
+
     @PersistenceContext
     private EntityManager entityManager;
 
@@ -521,6 +555,12 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     }
 
     private Specification<ExamStudent> buildSpecification(final ExamStudentSearchQuery query) {
+        List<ExamSubject> subjects = subjectService.listObjectiveScore(query.getExamId(), 0);
+        // 有客观题的科目代码
+        if (subjects != null && subjects.size() > 0) {
+            List<String> scodes = subjects.stream().map(e -> e.getCode()).collect(Collectors.toList());
+            query.setObjectiveCodes(scodes);
+        }
         return new Specification<ExamStudent>() {
 
             @Override
@@ -723,24 +763,29 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
                         predicates.add(cb.and(sub));
                     }
                 }
-                if (query.getObjectiveFill()!=null) {
-                	if(query.getObjectiveFill()){
-                		Predicate[] sub = new Predicate[objectiveAnswer.length];
+                if (query.getObjectiveFill() != null) {
+                    if (query.getObjectiveFill()) {
+                        Predicate[] sub = new Predicate[objectiveAnswer.length];
                         for (int i = 0; i < objectiveAnswer.length; i++) {
-                            sub[i] = cb.like(root.get("answers"), "%"+objectiveAnswer[i]+"%");
+                            sub[i] = cb.like(root.get("answers"), "%" + objectiveAnswer[i] + "%");
                         }
                         predicates.add(cb.or(sub));
-                	}else {
-                		Predicate[] orp = new Predicate[3];
-                		orp[0]=cb.isNull(root.get("answers"));
-                		orp[1]=cb.equal(root.get("answers"),"");
-                		Predicate[] sub = new Predicate[objectiveAnswer.length];
+                    } else {
+                        Predicate[] orp = new Predicate[3];
+                        orp[0] = cb.isNull(root.get("answers"));
+                        orp[1] = cb.equal(root.get("answers"), "");
+                        Predicate[] sub = new Predicate[objectiveAnswer.length];
                         for (int i = 0; i < objectiveAnswer.length; i++) {
-                            sub[i] = cb.notLike(root.get("answers"), "%"+objectiveAnswer[i]+"%");
+                            sub[i] = cb.notLike(root.get("answers"), "%" + objectiveAnswer[i] + "%");
                         }
-                        orp[2]=cb.and(sub);
+                        orp[2] = cb.and(sub);
                         predicates.add(cb.or(orp));
-                	}
+                        if (query.getObjectiveCodes() != null) {
+                            predicates.add(root.get("subjectCode").in(query.getObjectiveCodes()));
+                        } else {
+                            predicates.add(cb.equal(root.get("subjectCode"), UUID.randomUUID().toString()));
+                        }
+                    }
                 }
                 if (StringUtils.isNotBlank(query.getPaperType())) {
                     predicates.add(cb.equal(root.get("paperType"), query.getPaperType()));
@@ -1240,26 +1285,31 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
         return list.get(RandomUtils.nextInt(list.size()));
 
     }
+
     @Override
     public long countAllUploadByExamId(Integer examId) {
         Long count = studentDao.sumAllUploadByExamId(examId);
         return count == null ? 0 : count;
     }
+
     @Override
     public long countSubjectiveByExamId(Integer examId) {
         Long count = studentDao.sumSubjectiveByExamId(examId);
         return count == null ? 0 : count;
     }
+
     @Override
     public long countObjectiveByExamId(Integer examId) {
         Long count = studentDao.sumObjectiveByExamId(examId);
         return count == null ? 0 : count;
     }
+
     @Override
     public long countObjectivePageCountByExamId(Integer examId) {
         Long count = studentDao.sumObjectivePageCountByExamId(examId);
         return count == null ? 0 : count;
     }
+
     @Override
     public long countSheetCountByExamId(Integer examId) {
         Long count = studentDao.sumSheetCountByExamId(examId);
@@ -1495,7 +1545,8 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
         // }
         // if (query.getStudentIds() != null && query.getStudentIds().size() >
         // 0) {
-        // sql.append(" and s.id in("+StringUtils.join(query.getStudentIds(),",")+")");
+        // sql.append(" and s.id
+        // in("+StringUtils.join(query.getStudentIds(),",")+")");
         // }
         if (StringUtils.isNotBlank(query.getExamNumber())) {
             sql.append(" and s.exam_number='" + query.getExamNumber() + "'");
@@ -1677,7 +1728,7 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     }
 
     @SuppressWarnings("unchecked")
-	@Override
+    @Override
     public long countSheetCountByQuery(ExamStudentSearchQuery studentSearchQuery) {
         checkQuery(studentSearchQuery);
         if (studentSearchQuery.getSheetCount() != null) {
@@ -1688,21 +1739,22 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
         sql.append("from eb_exam_student s ");
         sql.append(getWhereSql(studentSearchQuery));
         Query query = entityManager.createNativeQuery(sql.toString());
-    	long ret=0;
-    	List<BigDecimal> list=query.getResultList(); 
-    	if(list!=null&&list.size()>0&&list.get(0)!=null) {
-    		ret=list.get(0).intValue() / 2;
-    	}
-    	
-    	if (studentSearchQuery.getSheetCount() != null) {
-    		studentSearchQuery.setSheetCount(studentSearchQuery.getSheetCount() / 2);
+        long ret = 0;
+        List<BigDecimal> list = query.getResultList();
+        if (list != null && list.size() > 0 && list.get(0) != null) {
+            ret = list.get(0).intValue() / 2;
         }
-    	return ret;
+
+        if (studentSearchQuery.getSheetCount() != null) {
+            studentSearchQuery.setSheetCount(studentSearchQuery.getSheetCount() / 2);
+        }
+        return ret;
     }
 
     @Override
-    public ExamStudent findBySchoolIdAndExamIdAndSubjectCodeAndStudentCode( Integer schoolId,Integer examId, String subjectCode, String studentCode){
-        return studentDao.findBySchoolIdAndExamIdAndSubjectCodeAndStudentCode( schoolId,examId, subjectCode,
+    public ExamStudent findBySchoolIdAndExamIdAndSubjectCodeAndStudentCode(Integer schoolId, Integer examId,
+            String subjectCode, String studentCode) {
+        return studentDao.findBySchoolIdAndExamIdAndSubjectCodeAndStudentCode(schoolId, examId, subjectCode,
                 studentCode);
     }
 
@@ -1717,8 +1769,8 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     }
 
     @Transactional
-	@Override
-	public boolean saveObjectivePageCount(ExamStudent student) {
-		return studentDao.updateObjectivePageCount(student.getId(), student.getObjectivePageCount()) > 0;
-	}
+    @Override
+    public boolean saveObjectivePageCount(ExamStudent student) {
+        return studentDao.updateObjectivePageCount(student.getId(), student.getObjectivePageCount()) > 0;
+    }
 }

+ 455 - 449
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectServiceImpl.java

@@ -51,454 +51,460 @@ import cn.com.qmth.stmms.common.enums.MarkStatus;
 @Service("examSubjectService")
 public class ExamSubjectServiceImpl extends BaseQueryService<ExamSubject> implements ExamSubjectService {
 
-	@Autowired
-	private ExamSubjectDao subjectDao;
-	@Autowired
-	private ExamService examService;
-	@Autowired
-	private ExamStudentDao examStudentDao;
-
-	@PersistenceContext
-	private EntityManager entityManager;
-
-	@Autowired
-	private MarkGroupService groupService;
-
-	@Autowired
-	private ExamStudentService studentService;
-
-	@Autowired
-	private CheckStudentService checkStudentService;
-
-	@Autowired
-	private MarkGroupService markGroupService;
-
-	@Autowired
-	private AnswerCardService answerCardService;
-
-	@Transactional
-	@Override
-	// @CachePut(value = "exam_subject_cache", key =
-	// "T(String).valueOf(#subject.examId)+'-'+#subject.code", condition =
-	// "#subject!=null && #subject.examId!=null && #subject.code!=null")
-	public ExamSubject save(ExamSubject subject) {
-		return subjectDao.save(subject);
-	}
-
-	@Override
-	// @Cacheable(value = "exam_subject_cache", key =
-	// "T(String).valueOf(#examId)+'-'+#code", condition =
-	// "#examId>0 && #code!=null")
-	public ExamSubject find(int examId, String code) {
-		return subjectDao.findByExamIdAndCode(examId, code);
-	}
-
-	@Override
-	public List<ExamSubject> list(int examId) {
-		return subjectDao.findByExamId(examId);
-	}
-
-	@Override
-	public List<ExamSubject> list(int examId, Set<String> codes) {
-		return subjectDao.findByExamIdAndSubjectCodeIn(examId, codes);
-	}
-
-	@Override
-	public List<String> listLevel(int examId) {
-		return subjectDao.findDistinctLevel(examId);
-	}
-
-	@Override
-	public List<String> listCategory(int examId) {
-		return subjectDao.findDistinctCategory(examId);
-	}
-
-	@Override
-	public List<ExamSubject> list(int examId, int uploadCountGt) {
-		return subjectDao.findByExamIdAndUploadCountGt(examId, uploadCountGt);
-	}
-
-	@Override
-	public long count(int examId) {
-		return subjectDao.countByExamId(examId);
-	}
-
-	@Override
-	public ExamSubjectSearchQuery findByQuery(ExamSubjectSearchQuery query) {
-		checkQuery(query);
-		Page<ExamSubject> result = subjectDao.findAll(buildSpecification(query), query);
-		fillResult(result, query);
-		return query;
-	}
-
-	@Override
-	public long countByQuery(ExamSubjectSearchQuery query) {
-		return subjectDao.count(buildSpecification(query));
-	}
-
-	@Transactional
-	@Override
-	// @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
-	// allEntries = true)
-	public void delete(ExamSubject markSubject) {
-		subjectDao.delete(markSubject);
-	}
-
-	@Transactional
-	@Override
-	// @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
-	// allEntries = true)
-	public void deleteByExamId(int examId) {
-		subjectDao.deleteByExamId(examId);
-	}
-
-	@Transactional
-	@Override
-	// @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
-	// allEntries = true)
-	public void updateTotalScore(int examId) {
-		subjectDao.updateTotalScoreByExamId(examId);
-	}
-
-	@Transactional
-	@Override
-	// @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
-	// allEntries = true)
-	public void updateScore(int examId, String code, boolean objective, double score) {
-		if (objective) {
-			subjectDao.updateObjectiveScore(examId, code, score);
-		} else {
-			subjectDao.updateSubjectiveScore(examId, code, score);
-		}
-		subjectDao.updateTotalScoreByExamIdAndCode(examId, code);
-	}
-
-	private Specification<ExamSubject> buildSpecification(final ExamSubjectSearchQuery query) {
-		return new Specification<ExamSubject>() {
-
-			@Override
-			public Predicate toPredicate(Root<ExamSubject> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
-				List<Predicate> predicates = new LinkedList<Predicate>();
-				if (query.getExamId() > 0) {
-					predicates.add(cb.equal(root.get("pk").get("examId"), query.getExamId()));
-				}
-				if (StringUtils.isNotEmpty(query.getCode())) {
-					predicates.add(cb.equal(root.get("pk").get("code"), query.getCode()));
-				}
-				if (StringUtils.isNotBlank(query.getLevel())) {
-					predicates.add(cb.equal(root.get("level"), query.getLevel()));
-				}
-				if (StringUtils.isNotBlank(query.getCategory())) {
-					predicates.add(cb.equal(root.get("category"), query.getCategory()));
-				}
-				if (query.getTotalScore() != null) {
-					predicates.add(cb.equal(root.get("totalScore"), query.getTotalScore()));
-				}
-				if (query.getTotalScoreNotEqual() != null) {
-					predicates.add(cb.notEqual(root.get("totalScore"), query.getTotalScoreNotEqual()));
-				}
-				if (query.getSubjectiveScoreNotEqual() != null) {
-					predicates.add(cb.notEqual(root.get("subjectiveScore"), query.getSubjectiveScoreNotEqual()));
-				}
-				if (query.getUploadCountGt() != null) {
-					predicates.add(cb.gt(root.get("uploadCount").as(Integer.class), query.getUploadCountGt()));
-				}
-				if (query.getUploadCountEqual() != null) {
-					predicates.add(cb.equal(root.get("uploadCount").as(Integer.class), query.getUploadCountEqual()));
-				}
-				if (query.getSelective() != null) {
-					predicates.add(cb.equal(root.get("selective"), query.getSelective()));
-				}
-				if (StringUtils.isNotBlank(query.getCodeIn())) {
-					String[] list = query.getCodeIn().split(",");
-					if (list.length > 0) {
-						Predicate[] sub = new Predicate[list.length];
-						for (int i = 0; i < list.length; i++) {
-							sub[i] = cb.equal(root.get("pk").get("code"), list[i]);
-						}
-						predicates.add(cb.or(sub));
-					}
-				}
-				if (StringUtils.isNotBlank(query.getCodeNotIn())) {
-					String[] list = query.getCodeNotIn().split(",");
-					if (list.length > 0) {
-						Predicate[] sub = new Predicate[list.length];
-						for (int i = 0; i < list.length; i++) {
-							sub[i] = cb.notEqual(root.get("pk").get("code"), list[i]);
-						}
-						predicates.add(cb.and(sub));
-					}
-				}
-				return predicates.isEmpty() ? cb.conjunction()
-						: cb.and(predicates.toArray(new Predicate[predicates.size()]));
-			}
-		};
-	}
-
-	@Override
-	@Transactional
-	public void updateUploadCount(Integer examId, String subjectCode, int count) {
-		subjectDao.updateUploadCount(examId, subjectCode, count);
-	}
-
-	@Override
-	public List<ExamSubject> listSubjectiveScore(int examId, double subjectiveScore) {
-		return subjectDao.listSubjectiveScore(examId, subjectiveScore);
-	}
-
-	@Override
-	@Transactional
-	public void updateSliceConfig(Integer examId, String subjectCode, List<PictureConfigItem> configList) {
-		subjectDao.updateSliceConfig(examId, subjectCode,
-				configList != null ? StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) : "");
-	}
-
-	@Transactional
-	@Override
-	public void updateTrialCount(int examId, String subjectCode, int trialCount) {
-		subjectDao.updateTrialCount(examId, subjectCode, trialCount);
-	}
-
-	@Override
-	public int findMaxInspectRound(int examId, Set<String> subjectCodes) {
-		StringBuilder sql = new StringBuilder("select max(s.inspect_round) from eb_exam_subject s ");
-		sql.append(" where s.exam_id=" + examId + " and s.code in ('" + StringUtils.join(subjectCodes, "','") + "')");
-		Query countQuery = entityManager.createNativeQuery(sql.toString());
-		Object singleResult = countQuery.getResultList().get(0);
-		Integer count = singleResult == null ? 0 : Integer.valueOf(singleResult.toString());
-		return count;
-	}
-
-	@Transactional
-	@Override
-	public void nextInspectRound(int examId, String subjectCode) {
-		subjectDao.nextInspectRound(examId, subjectCode);
-		examStudentDao.cancelInspect(examId, subjectCode, false, true);
-	}
-
-	@Transactional
-	@Override
-	public void updateSelective(int examId, String subjectCode, boolean selective) {
-		subjectDao.updateSelective(examId, subjectCode, selective);
-	}
-
-	@Override
-	public String enableExport(Exam exam, String subjectCode) {
-		ExamSubject subject = find(exam.getId(), subjectCode);
-		if (subject == null) {
-			return subjectCode + "该科目不存在";
-		}
-		List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(exam.getId(), subjectCode,
-				MarkStatus.FORMAL, MarkStatus.TRIAL);
-		if (groups != null && !groups.isEmpty()) {
-			return subjectCode + "评卷未完成";
-		}
-		if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-			return null;
-		}
-		if (DoubleUtil.sum(subject.getObjectiveScore(), subject.getSubjectiveScore()) == 0) {
-			return subjectCode + "科目总分为0";
-		}
-		long groupCount = groupService.countByExamAndSubject(exam.getId(), subjectCode);
-		if (subject.getSubjectiveScore() != null && subject.getSubjectiveScore() > 0 && groupCount == 0) {
-			return subjectCode + "未设置评卷分组";
-		}
-		if (checkStudentService.countByExamIdAndSubjectCodeAndChecked(exam.getId(), subjectCode, false) > 0) {
-			return subjectCode + "人工确认未完成";
-		}
-		ExamStudentSearchQuery query = new ExamStudentSearchQuery();
-		query.setExamId(exam.getId());
-		query.setUpload(false);
-		query.setManualAbsent(false);
-		query.setSubjectCode(subjectCode);
-		if (studentService.countByQuery(query) > 0) {
-			StringBuilder builder = new StringBuilder(subjectCode + "未上传考生必须人工指定缺考");
-			query.setPageSize(Integer.MAX_VALUE);
-			query = studentService.findByQuery(query);
-			for (ExamStudent s : query.getResult()) {
-				builder.append("," + s.getExamNumber());
-			}
-			return builder.toString();
-		}
-		query.setUpload(true);
-		query.setManualAbsent(true);
-		if (studentService.countByQuery(query) > 0) {
-			StringBuilder builder = new StringBuilder(subjectCode + "已上传考生有人工指定缺考");
-			query.setPageSize(Integer.MAX_VALUE);
-			query = studentService.findByQuery(query);
-			for (ExamStudent s : query.getResult()) {
-				builder.append("," + s.getExamNumber());
-			}
-			return builder.toString();
-		}
-		return null;
-	}
-
-	@Override
-	public Boolean checkSubjectAbsentForExport(Integer examId) {
-		ExamStudentSearchQuery query = new ExamStudentSearchQuery();
-		query.setExamId(examId);
-		query.setUpload(false);
-		query.setManualAbsent(false);
-		if (studentService.countByQuery(query) > 0) {
-			return false;
-		}
-		query.setUpload(true);
-		query.setManualAbsent(true);
-		if (studentService.countByQuery(query) > 0) {
-			return false;
-		}
-		return true;
-	}
-
-	@Override
-	@Transactional
-	public void updateCardType(int examId) {
-		List<ExamSubject> list = this.list(examId);
-		for (ExamSubject subject:list) {
-			AnswerCard answerCard = answerCardService.findByExamIdAndSubjectCode(examId,subject.getCode(), CardSource.WEB);
-			if(answerCard==null && FormatType.JSON.equals(subject.getCardType())){
-				subject.setCardType(null);
-				this.subjectDao.save(subject);
-			}
-		}
-	}
-
-	@Override
-	public Boolean checkSubjectForExport(Integer examId) {
-		Exam exam=examService.findById(examId);
-		if(exam==null) {
-			return false;
-		}
-		long groups = groupService.countByExamAndStatus(examId, MarkStatus.FORMAL, MarkStatus.TRIAL);
-		if (groups>0) {
-			return false;
-		}
-		if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-			return true;
-		}
-		if (subjectDao.getZeroScoreCount(examId)>0) {
-			return false;
-		}
-		long noGroupCount = subjectDao.getNoGroupCount(exam.getId());
-		if (noGroupCount>0) {
-			return false;
-		}
-
-		return true;
-	}
-
-	@Override
-	public List<Double> distinctTotalScore(int examId) {
-		return subjectDao.distinctTotalScore(examId);
-	}
-
-	@Transactional
-	@Override
-	public void resetInspect(int examId, String subjectCode) {
-		subjectDao.resetInspect(examId, subjectCode);
-	}
-
-	@Override
-	public List<ExamSubject> listObjectiveScore(Integer examId, double objectiveScoreGt) {
-		return subjectDao.listObjectiveScore(examId, objectiveScoreGt);
-	}
-
-	@Transactional
-	@Override
-	public String split(Integer schoolId, Integer examId, List<SubjectSplit> list) {
-		StringBuilder err = new StringBuilder();
-		if (CollectionUtils.isEmpty(list)) {
-			err.append("Excel中没有数据");
-			return err.toString();
-		}
-		int index = 0;
-		for (SubjectSplit vo : list) {
-			index++;
-			StringBuilder line = new StringBuilder();
-			if (StringUtils.isBlank(vo.getExamNumber())) {
-				line.append(" 准考证号不能为空");
-			}
-			if (StringUtils.isBlank(vo.getSubjectCode())) {
-				line.append(" 科目代码不能为空");
-			}
-			if (StringUtils.isBlank(vo.getSubjectName())) {
-				line.append(" 科目名称不能为空");
-			}
-			if (StringUtils.isNotBlank(vo.getExamNumber())) {
-				ExamStudent es = studentService.findByExamIdAndExamNumber(examId, vo.getExamNumber());
-				if (es == null) {
-					line.append(" 考生" + vo.getExamNumber() + "不存在");
-				} else {
-					vo.setStudent(es);
-				}
-			}
-			if (line.length() > 0) {
-				err.append(" 第" + (index + 2) + "行 " + line+"\r\n");
-			}
-		}
-		if (err.length() > 0) {
-			return err.toString();
-		}
-		try {
-			disposeSplit(schoolId, examId, list);
-		} catch (StatusException e) {
-			err.append(e.getDesc());
-			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
-		} catch (Exception e) {
-			err.append("导入出错:" + e.getMessage());
-			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
-		}
-		return err.toString();
-	}
-
-	private void disposeSplit(Integer schoolId, Integer examId, List<SubjectSplit> list) {
-		int index = 0;
-		Map<String,ExamSubject> validSubjects = new HashMap<>();
-		for (SubjectSplit vo : list) {
-			index++;
-			if(validSubjects.get(vo.getStudent().getSubjectCode())==null) { 
-				long groupCount = markGroupService.countByExamAndSubject(examId, vo.getStudent().getSubjectCode());
-				if (groupCount > 0) {
-					throw new StatusException(
-							" 第" + (index + 2) + "行 科目" + vo.getStudent().getSubjectCode() + "有分组,请先删除分组再执行");
-				}
-				ExamSubject es = subjectDao.findByExamIdAndCode(examId, vo.getStudent().getSubjectCode());
-				if(es==null) {
-					throw new StatusException(
-							" 第" + (index + 2) + "行 考生科目" + vo.getStudent().getSubjectCode() + "不存在");
-				}
-				validSubjects.put(vo.getStudent().getSubjectCode(),es);
-			}
-			if (validSubjects.get(vo.getSubjectCode())==null) {
-				ExamSubject es = subjectDao.findByExamIdAndCode(examId, vo.getSubjectCode());
-				if (es == null) {
-					es = new ExamSubject();
-					es.setExamId(examId);
-					es.setName(vo.getSubjectName());
-					es.setCode(vo.getSubjectCode());
-					es.setObjectiveScore(0.0);
-					es.setSubjectiveScore(0.0);
-					es.setTotalScore(0.0);
-					es.setUploadCount(0);
-					es.setDisplayQuestionName(true);
-					es.setInspectRound(1);
-					es.setSelective(false);
-					subjectDao.saveAndFlush(es);
-				} else {
-					long count = markGroupService.countByExamAndSubject(examId, vo.getSubjectCode());
-					if (count > 0) {
-						throw new StatusException(" 第" + (index + 2) + "行 科目" + vo.getSubjectCode() + "有分组,请先删除分组再执行");
-					}
-				}
-				validSubjects.put(vo.getSubjectCode(),es);
-			}
-			vo.getStudent().setSubjectCode(validSubjects.get(vo.getSubjectCode()).getCode());
-			vo.getStudent().setSubjectName(validSubjects.get(vo.getSubjectCode()).getName());
-			examStudentDao.updateSubject(vo.getStudent().getId(),vo.getStudent().getSubjectCode(),vo.getStudent().getSubjectName());
-		}
-		subjectDao.updateUploadCountByExamId(examId);
-		subjectDao.deleteNoStudentByExamId(examId);
-	}
+    @Autowired
+    private ExamSubjectDao subjectDao;
+
+    @Autowired
+    private ExamService examService;
+
+    @Autowired
+    private ExamStudentDao examStudentDao;
+
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    @Autowired
+    private MarkGroupService groupService;
+
+    @Autowired
+    private ExamStudentService studentService;
+
+    @Autowired
+    private CheckStudentService checkStudentService;
+
+    @Autowired
+    private MarkGroupService markGroupService;
+
+    @Autowired
+    private AnswerCardService answerCardService;
+
+    @Transactional
+    @Override
+    // @CachePut(value = "exam_subject_cache", key =
+    // "T(String).valueOf(#subject.examId)+'-'+#subject.code", condition =
+    // "#subject!=null && #subject.examId!=null && #subject.code!=null")
+    public ExamSubject save(ExamSubject subject) {
+        return subjectDao.save(subject);
+    }
+
+    @Override
+    // @Cacheable(value = "exam_subject_cache", key =
+    // "T(String).valueOf(#examId)+'-'+#code", condition =
+    // "#examId>0 && #code!=null")
+    public ExamSubject find(int examId, String code) {
+        return subjectDao.findByExamIdAndCode(examId, code);
+    }
+
+    @Override
+    public List<ExamSubject> list(int examId) {
+        return subjectDao.findByExamId(examId);
+    }
+
+    @Override
+    public List<ExamSubject> list(int examId, Set<String> codes) {
+        return subjectDao.findByExamIdAndSubjectCodeIn(examId, codes);
+    }
+
+    @Override
+    public List<String> listLevel(int examId) {
+        return subjectDao.findDistinctLevel(examId);
+    }
+
+    @Override
+    public List<String> listCategory(int examId) {
+        return subjectDao.findDistinctCategory(examId);
+    }
+
+    @Override
+    public List<ExamSubject> list(int examId, int uploadCountGt) {
+        return subjectDao.findByExamIdAndUploadCountGt(examId, uploadCountGt);
+    }
+
+    @Override
+    public long count(int examId) {
+        return subjectDao.countByExamId(examId);
+    }
+
+    @Override
+    public ExamSubjectSearchQuery findByQuery(ExamSubjectSearchQuery query) {
+        checkQuery(query);
+        Page<ExamSubject> result = subjectDao.findAll(buildSpecification(query), query);
+        fillResult(result, query);
+        return query;
+    }
+
+    @Override
+    public long countByQuery(ExamSubjectSearchQuery query) {
+        return subjectDao.count(buildSpecification(query));
+    }
+
+    @Transactional
+    @Override
+    // @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
+    // allEntries = true)
+    public void delete(ExamSubject markSubject) {
+        subjectDao.delete(markSubject);
+    }
+
+    @Transactional
+    @Override
+    // @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
+    // allEntries = true)
+    public void deleteByExamId(int examId) {
+        subjectDao.deleteByExamId(examId);
+    }
+
+    @Transactional
+    @Override
+    // @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
+    // allEntries = true)
+    public void updateTotalScore(int examId) {
+        subjectDao.updateTotalScoreByExamId(examId);
+    }
+
+    @Transactional
+    @Override
+    // @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
+    // allEntries = true)
+    public void updateScore(int examId, String code, boolean objective, double score) {
+        if (objective) {
+            subjectDao.updateObjectiveScore(examId, code, score);
+        } else {
+            subjectDao.updateSubjectiveScore(examId, code, score);
+        }
+        subjectDao.updateTotalScoreByExamIdAndCode(examId, code);
+    }
+
+    private Specification<ExamSubject> buildSpecification(final ExamSubjectSearchQuery query) {
+        return new Specification<ExamSubject>() {
+
+            @Override
+            public Predicate toPredicate(Root<ExamSubject> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+                if (query.getExamId() > 0) {
+                    predicates.add(cb.equal(root.get("pk").get("examId"), query.getExamId()));
+                }
+                if (StringUtils.isNotEmpty(query.getCode())) {
+                    predicates.add(cb.equal(root.get("pk").get("code"), query.getCode()));
+                }
+                if (StringUtils.isNotBlank(query.getLevel())) {
+                    predicates.add(cb.equal(root.get("level"), query.getLevel()));
+                }
+                if (StringUtils.isNotBlank(query.getCategory())) {
+                    predicates.add(cb.equal(root.get("category"), query.getCategory()));
+                }
+                if (query.getTotalScore() != null) {
+                    predicates.add(cb.equal(root.get("totalScore"), query.getTotalScore()));
+                }
+                if (query.getTotalScoreNotEqual() != null) {
+                    predicates.add(cb.notEqual(root.get("totalScore"), query.getTotalScoreNotEqual()));
+                }
+                if (query.getSubjectiveScoreNotEqual() != null) {
+                    predicates.add(cb.notEqual(root.get("subjectiveScore"), query.getSubjectiveScoreNotEqual()));
+                }
+                if (query.getUploadCountGt() != null) {
+                    predicates.add(cb.gt(root.get("uploadCount").as(Integer.class), query.getUploadCountGt()));
+                }
+                if (query.getUploadCountEqual() != null) {
+                    predicates.add(cb.equal(root.get("uploadCount").as(Integer.class), query.getUploadCountEqual()));
+                }
+                if (query.getSelective() != null) {
+                    predicates.add(cb.equal(root.get("selective"), query.getSelective()));
+                }
+                if (StringUtils.isNotBlank(query.getCodeIn())) {
+                    String[] list = query.getCodeIn().split(",");
+                    if (list.length > 0) {
+                        Predicate[] sub = new Predicate[list.length];
+                        for (int i = 0; i < list.length; i++) {
+                            sub[i] = cb.equal(root.get("pk").get("code"), list[i]);
+                        }
+                        predicates.add(cb.or(sub));
+                    }
+                }
+                if (StringUtils.isNotBlank(query.getCodeNotIn())) {
+                    String[] list = query.getCodeNotIn().split(",");
+                    if (list.length > 0) {
+                        Predicate[] sub = new Predicate[list.length];
+                        for (int i = 0; i < list.length; i++) {
+                            sub[i] = cb.notEqual(root.get("pk").get("code"), list[i]);
+                        }
+                        predicates.add(cb.and(sub));
+                    }
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        };
+    }
+
+    @Override
+    @Transactional
+    public void updateUploadCount(Integer examId, String subjectCode, int count) {
+        subjectDao.updateUploadCount(examId, subjectCode, count);
+    }
+
+    @Override
+    public List<ExamSubject> listSubjectiveScore(int examId, double subjectiveScore) {
+        return subjectDao.listSubjectiveScore(examId, subjectiveScore);
+    }
+
+    @Override
+    @Transactional
+    public void updateSliceConfig(Integer examId, String subjectCode, List<PictureConfigItem> configList) {
+        subjectDao.updateSliceConfig(examId, subjectCode,
+                configList != null ? StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) : "");
+    }
+
+    @Transactional
+    @Override
+    public void updateTrialCount(int examId, String subjectCode, int trialCount) {
+        subjectDao.updateTrialCount(examId, subjectCode, trialCount);
+    }
+
+    @Override
+    public int findMaxInspectRound(int examId, Set<String> subjectCodes) {
+        StringBuilder sql = new StringBuilder("select max(s.inspect_round) from eb_exam_subject s ");
+        sql.append(" where s.exam_id=" + examId + " and s.code in ('" + StringUtils.join(subjectCodes, "','") + "')");
+        Query countQuery = entityManager.createNativeQuery(sql.toString());
+        Object singleResult = countQuery.getResultList().get(0);
+        Integer count = singleResult == null ? 0 : Integer.valueOf(singleResult.toString());
+        return count;
+    }
+
+    @Transactional
+    @Override
+    public void nextInspectRound(int examId, String subjectCode) {
+        subjectDao.nextInspectRound(examId, subjectCode);
+        examStudentDao.cancelInspect(examId, subjectCode, false, true);
+    }
+
+    @Transactional
+    @Override
+    public void updateSelective(int examId, String subjectCode, boolean selective) {
+        subjectDao.updateSelective(examId, subjectCode, selective);
+    }
+
+    @Override
+    public String enableExport(Exam exam, String subjectCode) {
+        ExamSubject subject = find(exam.getId(), subjectCode);
+        if (subject == null) {
+            return subjectCode + "该科目不存在";
+        }
+        List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(exam.getId(), subjectCode,
+                MarkStatus.FORMAL, MarkStatus.TRIAL);
+        if (groups != null && !groups.isEmpty()) {
+            return subjectCode + "评卷未完成";
+        }
+        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
+            return null;
+        }
+        if (DoubleUtil.sum(subject.getObjectiveScore(), subject.getSubjectiveScore()) == 0) {
+            return subjectCode + "科目总分为0";
+        }
+        long groupCount = groupService.countByExamAndSubject(exam.getId(), subjectCode);
+        if (subject.getSubjectiveScore() != null && subject.getSubjectiveScore() > 0 && groupCount == 0) {
+            return subjectCode + "未设置评卷分组";
+        }
+        if (checkStudentService.countByExamIdAndSubjectCodeAndChecked(exam.getId(), subjectCode, false) > 0) {
+            return subjectCode + "人工确认未完成";
+        }
+        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+        query.setExamId(exam.getId());
+        query.setUpload(false);
+        query.setManualAbsent(false);
+        query.setSubjectCode(subjectCode);
+        if (studentService.countByQuery(query) > 0) {
+            StringBuilder builder = new StringBuilder(subjectCode + "未上传考生必须人工指定缺考");
+            query.setPageSize(Integer.MAX_VALUE);
+            query = studentService.findByQuery(query);
+            for (ExamStudent s : query.getResult()) {
+                builder.append("," + s.getExamNumber());
+            }
+            return builder.toString();
+        }
+        query.setUpload(true);
+        query.setManualAbsent(true);
+        if (studentService.countByQuery(query) > 0) {
+            StringBuilder builder = new StringBuilder(subjectCode + "已上传考生有人工指定缺考");
+            query.setPageSize(Integer.MAX_VALUE);
+            query = studentService.findByQuery(query);
+            for (ExamStudent s : query.getResult()) {
+                builder.append("," + s.getExamNumber());
+            }
+            return builder.toString();
+        }
+        return null;
+    }
+
+    @Override
+    public Boolean checkSubjectAbsentForExport(Integer examId) {
+        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+        query.setExamId(examId);
+        query.setUpload(false);
+        query.setManualAbsent(false);
+        if (studentService.countByQuery(query) > 0) {
+            return false;
+        }
+        query.setUpload(true);
+        query.setManualAbsent(true);
+        if (studentService.countByQuery(query) > 0) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional
+    public void updateCardType(int examId) {
+        List<ExamSubject> list = this.list(examId);
+        for (ExamSubject subject : list) {
+            AnswerCard answerCard = answerCardService.findByExamIdAndSubjectCode(examId, subject.getCode(),
+                    CardSource.WEB);
+            if (answerCard == null && FormatType.JSON.equals(subject.getCardType())) {
+                subject.setCardType(null);
+                this.subjectDao.save(subject);
+            }
+        }
+    }
+
+    @Override
+    public Boolean checkSubjectForExport(Integer examId) {
+        Exam exam = examService.findById(examId);
+        if (exam == null) {
+            return false;
+        }
+        long groups = groupService.countByExamAndStatus(examId, MarkStatus.FORMAL, MarkStatus.TRIAL);
+        if (groups > 0) {
+            return false;
+        }
+        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
+            return true;
+        }
+        if (subjectDao.getZeroScoreCount(examId) > 0) {
+            return false;
+        }
+        long noGroupCount = subjectDao.getNoGroupCount(exam.getId());
+        if (noGroupCount > 0) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public List<Double> distinctTotalScore(int examId) {
+        return subjectDao.distinctTotalScore(examId);
+    }
+
+    @Transactional
+    @Override
+    public void resetInspect(int examId, String subjectCode) {
+        subjectDao.resetInspect(examId, subjectCode);
+    }
+
+    @Override
+    public List<ExamSubject> listObjectiveScore(Integer examId, double objectiveScoreGt) {
+        return subjectDao.listObjectiveScore(examId, objectiveScoreGt);
+    }
+
+    @Transactional
+    @Override
+    public String split(Integer schoolId, Integer examId, List<SubjectSplit> list) {
+        StringBuilder err = new StringBuilder();
+        if (CollectionUtils.isEmpty(list)) {
+            err.append("Excel中没有数据");
+            return err.toString();
+        }
+        int index = 0;
+        for (SubjectSplit vo : list) {
+            index++;
+            StringBuilder line = new StringBuilder();
+            if (StringUtils.isBlank(vo.getExamNumber())) {
+                line.append(" 准考证号不能为空");
+            }
+            if (StringUtils.isBlank(vo.getSubjectCode())) {
+                line.append(" 科目代码不能为空");
+            }
+            if (StringUtils.isBlank(vo.getSubjectName())) {
+                line.append(" 科目名称不能为空");
+            }
+            if (StringUtils.isNotBlank(vo.getExamNumber())) {
+                ExamStudent es = studentService.findByExamIdAndExamNumber(examId, vo.getExamNumber());
+                if (es == null) {
+                    line.append(" 考生" + vo.getExamNumber() + "不存在");
+                } else {
+                    vo.setStudent(es);
+                }
+            }
+            if (line.length() > 0) {
+                err.append(" 第" + (index + 2) + "行 " + line + "\r\n");
+            }
+        }
+        if (err.length() > 0) {
+            return err.toString();
+        }
+        try {
+            disposeSplit(schoolId, examId, list);
+        } catch (StatusException e) {
+            err.append(e.getDesc());
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+        } catch (Exception e) {
+            err.append("导入出错:" + e.getMessage());
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+        }
+        return err.toString();
+    }
+
+    private void disposeSplit(Integer schoolId, Integer examId, List<SubjectSplit> list) {
+        int index = 0;
+        Map<String, ExamSubject> validSubjects = new HashMap<>();
+        for (SubjectSplit vo : list) {
+            index++;
+            if (validSubjects.get(vo.getStudent().getSubjectCode()) == null) {
+                long groupCount = markGroupService.countByExamAndSubject(examId, vo.getStudent().getSubjectCode());
+                if (groupCount > 0) {
+                    throw new StatusException(
+                            " 第" + (index + 2) + "行 科目" + vo.getStudent().getSubjectCode() + "有分组,请先删除分组再执行");
+                }
+                ExamSubject es = subjectDao.findByExamIdAndCode(examId, vo.getStudent().getSubjectCode());
+                if (es == null) {
+                    throw new StatusException(" 第" + (index + 2) + "行 考生科目" + vo.getStudent().getSubjectCode() + "不存在");
+                }
+                validSubjects.put(vo.getStudent().getSubjectCode(), es);
+            }
+            if (validSubjects.get(vo.getSubjectCode()) == null) {
+                ExamSubject es = subjectDao.findByExamIdAndCode(examId, vo.getSubjectCode());
+                if (es == null) {
+                    es = new ExamSubject();
+                    es.setExamId(examId);
+                    es.setName(vo.getSubjectName());
+                    es.setCode(vo.getSubjectCode());
+                    es.setObjectiveScore(0.0);
+                    es.setSubjectiveScore(0.0);
+                    es.setTotalScore(0.0);
+                    es.setUploadCount(0);
+                    es.setDisplayQuestionName(true);
+                    es.setInspectRound(1);
+                    es.setSelective(false);
+                    subjectDao.saveAndFlush(es);
+                } else {
+                    // long count =
+                    // markGroupService.countByExamAndSubject(examId,
+                    // vo.getSubjectCode());
+                    // if (count > 0) {
+                    // throw new StatusException(" 第" + (index + 2) + "行 科目" +
+                    // vo.getSubjectCode() + "有分组,请先删除分组再执行");
+                    // }
+                }
+                validSubjects.put(vo.getSubjectCode(), es);
+            }
+            vo.getStudent().setSubjectCode(validSubjects.get(vo.getSubjectCode()).getCode());
+            vo.getStudent().setSubjectName(validSubjects.get(vo.getSubjectCode()).getName());
+            examStudentDao.updateSubject(vo.getStudent().getId(), vo.getStudent().getSubjectCode(),
+                    vo.getStudent().getSubjectName());
+        }
+        subjectDao.updateUploadCountByExamId(examId);
+        subjectDao.deleteNoStudentByExamId(examId);
+    }
 
 }