背景
一般情况下,我们从数据获读取大量数据,一般通过像这样的sql来查询
select * from xxx a where a.id in (x,x,x)
发现没有,用 in 语句来查询,但是相比于join,in的查询效率要低很多
那如何提高查询效率呢?如何用join来查询,因为一般情况下,我们有id了,怎么跟表关联有关呢?
解决办法
创建临时表,我们可以创建一个tempKey表,专门存放要查询的key。注意一下几点
- tempKey表就是临时表,所以每次使用前删掉
- 删掉后直接插入要查询的Id到该表中
- 然后就可以关联tempkey表查询了
下面,我写个工具类,可以供参考
package com.future.springcloud.common;
import com.future.springcloud.dao.TmpKeyMapper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.function.Function;
@Service
public class MapperUtils {
@Autowired
private SqlSessionFactory factory;
/**
* 方法说明:batchSelectByKeys
*
* @param clasz dao类
* @param data 要查询数据的Id
* @param function 回调
* @param <U> 参数
* @param <R> 返回参数
* @return 返回结果
* @throws SQLException
*/
public <U, R> R batchSelectByKeys(Class<U> clasz, List<Integer> data, Function<U, R> function) throws SQLException {
R result = null;
SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false);
Connection conn = sqlSession.getConnection();
try {
final boolean autoCommit = conn.getAutoCommit();
try {
if (autoCommit) {
conn.setAutoCommit(false);
}
TmpKeyMapper mapper = sqlSession.getMapper(TmpKeyMapper.class);
// 查询前先清空tmp_key表
mapper.clear();
for (Integer id : data) {
// 把key插入到临时表
mapper.insert(id);
}
U obj = sqlSession.getMapper(clasz);
// 执行查询操作
result = function.apply(obj);
// 提交任务
conn.commit();
} catch (Exception e) {
if (autoCommit) {
conn.rollback();
}
}
} catch (SQLException e) {
String errorMessage = "something error on invoke method batchInsert";
e.printStackTrace();
throw new RuntimeException(errorMessage, e);
} finally {
conn.close();
sqlSession.close();
}
return result;
}
}
其中,TmpKeyMapper类代码如下
package com.future.springcloud.dao;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface TmpKeyMapper {
/**
*
* @param id 插入临时表的Key值
*/
@Insert("insert into tmp_key (id) values (#{id})")
void insert(@Param("id") Integer id);
/**
* 清空临时表
*/
@Delete("delete from tmp_key")
void clear();
}
使用
这个工具类怎么使用?不知道的朋友可以看下面的代码
@Mapper
public interface PaymentDao {
int create(Payment payment);
Payment getPaymentById(@Param("id") int id);
@Select(" SELECT * from payment a INNER join tmp_key b on a.id=b.id ")
Payment getPaymentByIds();
}
package com.future.springcloud.service.imp;
import com.future.springcloud.common.MapperUtils;
import com.future.springcloud.dao.PaymentDao;
import com.future.springcloud.entities.Payment;
import com.future.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
@Resource
private MapperUtils mapperUtils;
public Payment getPaymentById(int id){
Payment payment = null;
try {
payment = mapperUtils.batchSelectByKeys(PaymentDao.class,Arrays.asList(id),PaymentDao::getPaymentByIds);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return payment;
}
}
以上方法非常有效,大公司一般都是用这种方法查询数据量大的数据,避免使用in查询。
好久没更新文章了,希望以后能多多分享更多更好的技术,喜欢的可以点赞分享!!
|