package org.zstack.core.db; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.transaction.annotation.Transactional; import javax.persistence.LockModeType; import javax.persistence.Query; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by xing5 on 2017/1/11. */ @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class SQL { @Autowired private DatabaseFacade dbf; private String sql; private Query query; private Class entityClass; private Map<String, Object> params = new HashMap<>(); private Integer first; private Integer max; private LockModeType lockMode; private SQL(String sql) { this.sql = sql; query = dbf.getEntityManager().createQuery(this.sql); } private SQL(String sql, Class returnClass) { this.sql = sql; entityClass = returnClass; query = dbf.getEntityManager().createQuery(this.sql, returnClass); } public SQL param(String key, Object o) { query.setParameter(key, o); params.put(key, o); return this; } public SQL offset(int offset) { query.setFirstResult(offset); first = offset; return this; } public SQL limit(int max) { query.setMaxResults(max); this.max = max; return this; } public SQL lock(LockModeType mode) { query.setLockMode(mode); lockMode = mode; return this; } @Transactional(readOnly = true) private List transactionalList() { rebuildQueryInTransaction(); return query.getResultList(); } public <T> List<T> list() { return transactionalList(); } @Transactional(readOnly = true) private <K> K transactionalFind() { rebuildQueryInTransaction(); List lst = query.getResultList(); return lst.isEmpty() ? null : (K) lst.get(0); } private void rebuildQueryInTransaction() { query = entityClass == null ? dbf.getEntityManager().createQuery(sql) : dbf.getEntityManager().createQuery(sql, entityClass); if (first != null) { query.setFirstResult(first); } if (lockMode != null) { query.setLockMode(lockMode); } if (max != null) { query.setMaxResults(max); } for (Map.Entry<String, Object> e : params.entrySet()) { query.setParameter(e.getKey(), e.getValue()); } } public <K> K find() { return transactionalFind(); } @Transactional private int transactionalExecute() { rebuildQueryInTransaction(); int ret = query.executeUpdate(); dbf.getEntityManager().flush(); return ret; } public int execute() { return transactionalExecute(); } public static UpdateQuery New(Class entityClass) { return UpdateQuery.New(entityClass); } public static SQL New(String sql) { return new SQL(sql); } public static SQL New(String sql, Class returnClass) { return new SQL(sql, returnClass); } }