/*
* Copyright 2008-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.geequery.springdata.repository.query;
import java.util.List;
import java.util.NoSuchElementException;
import javax.persistence.PersistenceException;
import jef.database.NativeQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.orm.jpa.EntityManagerProxy;
import com.github.geequery.springdata.repository.query.GqParameters.GqParameter;
/**
* 基于Query的Spring-data查询
*/
final class GqNativeQuery extends AbstractGqQuery {
private NativeQuery<?> query;
private Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Creates a new {@link GqNativeQuery}.
*/
GqNativeQuery(GqQueryMethod method, EntityManagerProxy em, NativeQuery<?> nq) {
super(method, em);
this.query = nq;
}
@Override
protected List<?> getResultList(Object[] values, Pageable page) {
NativeQuery<?> query = getThreadQuery();
if (page != null) {
query.setRange(page.getOffset(), page.getPageSize());
assertNoSort(page.getSort());
}
applyParamters(query, values);
return query.getResultList();
}
private void assertNoSort(Sort sort) {
if (sort != null) {
log.warn("The input parameter Sort [" + sort + "]can not be set into a SQL Query, and was ignored.");
}
}
@Override
protected Object getSingleResult(Object[] values) {
NativeQuery<?> query = getThreadQuery();
applyParamters(query, values);
return query.getSingleResult();
}
@Override
protected int executeUpdate(Object[] values) {
NativeQuery<?> query = getThreadQuery();
applyParamters(query, values);
return query.executeUpdate();
}
@Override
protected int executeDelete(Object[] values) {
NativeQuery<?> query = getThreadQuery();
applyParamters(query, values);
return query.executeUpdate();
}
@Override
protected long getResultCount(Object[] values) {
NativeQuery<?> query = getThreadQuery();
applyParamters(query, values);
return query.getResultCount();
}
private void applyParamters(NativeQuery<?> query, Object[] values) {
GqParameters ps = getQueryMethod().getParameters();
int i = 0;
for (GqParameter p : ps) {
Object obj = values[i++];
if (p.isSpecialParameter()) {
if(Sort.class.isAssignableFrom(p.getType())){
assertNoSort((Sort)obj);
}
continue;
}
if (p.getIgnoreIf() != null && QueryUtils.isIgnore(p.getIgnoreIf(), obj)) {
continue;
}
if (p.isNamedParameter()) {
try {
query.setParameter(p.getName(), obj);
} catch (NoSuchElementException e) {
throw new PersistenceException("The parameter [:" + p.getName() + "] is not defined in the query '" + super.getQueryMethod().getName()
+ "', please make sure there is \":name\" expression in the Query.", e);
}
} else {
try {
// 写在Query中的参数一般都是 ?1 ?2从1开始的,而方法的参数序号是从0开始的,因此+1
query.setParameter(p.getIndex() + 1, obj);
} catch (NoSuchElementException e) {
throw new PersistenceException("The parameter [?" + (p.getIndex() + 1) + "] is not defined in the query '" + super.getQueryMethod().getName()
+ "', please make sure that using @Param(\"name\") to mapping parameter into query.", e);
}
}
}
}
private NativeQuery<?> getThreadQuery() {
return query.rebind(getSession(), null);
}
}