有时我们需要在不同的数据中查询数据时,会在mybatis的xml文件中动态地注入表名
-
1.因此我们需要在配置文件中先配置数据库名称:
此处配置了数据库名称 -
2.然后在代码中注入这个属性值:
注入数据库名称 -
3.修改mapper接口接收的参数:
map中接收数据库名称这个参数 - 4.在mybatis的xml文件中使用
${nicsuser}
取表名,用#{}
正常取参数,
由于表名或者数字类型不要自动加上单引号,所以用${}取值,其它参数由于需要在取出的值中自动加上单引号,所以用#{}取值
延伸:预编译和非预编译
- 预编译就是SQL提前编译好,在#{}的地方自动处理成?,然后再注入传递的参数即可,预编译由于会提前编译好SQL,所以会防止出现SQL注入的问题
<!--采用预编译,使用${nicsuer}取动态注入的表名,
此时取到的表名不会被加上单引号,使用#{}正产取得的参数值会自动加上单引号-->
<select id="nicsNeSpecListForAll" parameterType="map" resultType="NeSpecMappingQueryVo">
select nef.PRODUCTNAME nicsNeSpecName,
nef.VERSION nicsNeSpecVersion,
nef.factoryName factoryName,
nef.factoryId factoryId,
emp.name resourcesNeSpecName,
emp.restype restype,
emp.specMappingId
from (select distinct ne.PRODUCTNAME,
ne.VERSION,
f.name factoryName,
f.id factoryId
from ${nicsuser}.v_nics_ne ne,
t_pub_factory f,
t_nics_ems_mapping em
where ne.EMS = em.ems_name
and f.id = em.factory_id
and ne.DELETED = 0
and em.del_flag = 0) nef,
(select e.name,
mp.restype,
mp.nics_spec_name,
mp.id specMappingId
from t_spec_entity e,
t_nics_spec_mapping mp
where e.id = mp.spec_id
and mp.del_flag = 0) emp
where nef.PRODUCTNAME = emp.nics_spec_name(+)
<if test="factoryId !=null and factoryId !=''">
and nef.factoryId = #{factoryId}
</if>
<if test="nicsNeSpecName !=null and nicsNeSpecName !=''">
and nef.PRODUCTNAME like '%'|| #{nicsNeSpecName}||'%'
</if>
</select>
这里就是预编译Preparing,他将分页参数的占位符编译成问号,然后等分页参数传递进来即可分页-1
<!--映射板卡规格查询(查全部,包含未映射和已映射的)-->
<select id="nicsCardSpecListForAll" parameterType="map" resultType="CardSpecMappingQueryVo" >
select vcf.installedequipmentobjecttype nicsCardSpecName,
vcf.neportNumber nicsCardSpecPortCount,
vcf.installedversion nicsCardSpecVersion,
vcf.factoryName factoryName,
vcf.factoryId factoryId,
emp.nics_spec_name resourcesCardSpecName,
emp.logogram logogram,
emp.specEntityId,
emp.specMappingId
from
(select vc.installedequipmentobjecttype,
vc.installedversion,
count(distinct vc.installedequipmentobjecttype || vc.installedversion ||
nep.PORTNO) neportNumber,
f.name factoryName,
f.id factoryId
from ${nicsuser}.v_nics_card vc,
${nicsuser}.v_nics_neport nep,
t_pub_factory f,
t_nics_ems_mapping em
where vc.id = nep.CARD_ID
and vc.ems = em.ems_name
and em.factory_id = f.id
and vc.deleted = 0
group by vc.INSTALLEDEQUIPMENTOBJECTTYPE, vc.INSTALLEDVERSION,f.name,f.id
union all
select vc.installedequipmentobjecttype,
vc.installedversion,
0,
f.name factoryName,
f.id factoryId
from ${nicsuser}.v_nics_card vc,
t_pub_factory f,
t_nics_ems_mapping em
where vc.ems = em.ems_name
and em.factory_id = f.id
and vc.deleted = 0
and vc.id not in (select nep.CARD_ID from ${nicsuser}.v_nics_neport nep)
group by vc.INSTALLEDEQUIPMENTOBJECTTYPE, vc.INSTALLEDVERSION, f.name,f.id) vcf,
(select e.name,
e.id specEntityId,
cp.logogram,
mp.restype,
mp.nics_spec_name,
mp.id specMappingId
from t_spec_entity e,
t_spec_cardprop cp,
t_nics_spec_mapping mp
where e.id = mp.spec_id
and e.specprop_id = cp.id
and mp.del_flag = 0) emp
where vcf.installedequipmentobjecttype = emp.nics_spec_name(+)
<if test="factoryId !=null and factoryId !=''">
and vcf.factoryId = #{factoryId}
</if>
<if test="nicsCardSpecName !=null and nicsCardSpecName !=''">
and vcf.installedequipmentobjecttype like '%'|| #{nicsCardSpecName}||'%'
</if>
</select>
这里就是预编译Preparing,他将分页参数的占位符编译成问号,然后等分页参数传递进来即可分页-2
-非预编译,就是说SQL不会提前编译,在执行的时候才把传递的参数传进来,这样的话就会有SQL注入的风险,比如在SQL执行的时候恶意传入一些误操作的例如drop table的SQL操作关键字等,由于SQL没有预编译而是直接拿着传递进来的参数执行SQL的,这样就有很高的风险,也容易报错
<!--statementType="STATEMENT"参数,让SQL非预编译执行-->
<!--映射网元规格查询(查询已经映射的)-->
<select id="nicsNeSpecListForAll" parameterType="map" resultType="NeSpecMappingQueryVo" statementType="STATEMENT">
select nef.PRODUCTNAME nicsNeSpecName,
nef.VERSION nicsNeSpecVersion,
nef.factoryName factoryName,
nef.factoryId factoryId,
emp.name resourcesNeSpecName,
emp.restype restype,
emp.specMappingId
from (select distinct ne.PRODUCTNAME,
ne.VERSION,
f.name factoryName,
f.id factoryId
from ${nicsuser}.v_nics_ne ne,
t_pub_factory f,
t_nics_ems_mapping em
where ne.EMS = em.ems_name
and f.id = em.factory_id
and ne.DELETED = 0
and em.del_flag = 0) nef,
(select e.name,
mp.restype,
mp.nics_spec_name,
mp.id specMappingId
from t_spec_entity e,
t_nics_spec_mapping mp
where e.id = mp.spec_id
and mp.del_flag = 0) emp
where nef.PRODUCTNAME = emp.nics_spec_name(+)
<if test="factoryId !=null and factoryId !=''">
and nef.factoryId = #{factoryId}
</if>
<if test="nicsNeSpecName !=null and nicsNeSpecName !=''">
and nef.PRODUCTNAME like '%'|| #{nicsNeSpecName}||'%'
</if>
</select>
Executing,此时是非预编译,SQL直接执行,由于此时分页参数还没有准备好这样直接执行SQL 的结果就是出现并非所有变量都已绑定的错误
SQL报错了,分页的参数没有传进来的缘故,所以会报错
遇到需要分页的这种情况一定不要用非预编译,不然分页参数没有传进来的时候就出现上面那种SQL错误,
区别:
- 预编译可以将?解析为占位符等待参数传入,然后执行SQL
- 非预编译会直接执行SQL,然后会把?直接当成SQL中的参数来执行,所以在分页参数没有传进来替换?时,SQL直接执行就报错了
网友评论