当前位置:首页 » 编程语言 » sql代码是写mapper里吗
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

sql代码是写mapper里吗

发布时间: 2022-08-03 01:53:12

Ⅰ 如何开发自己的通用Mapper

第一步,创建HsqldbMapper<T>
public interface HsqldbMapper<T> {
}
这个接口就是我们定义的通用Mapper,具体的接口方法在**第三步**写。其他的Mapper可以继承这个HsqldbMapper<T>。

第二部,创建HsqldbProvider
public class HsqldbProvider extends MapperTemplate {
//继承父类的方法
public HsqldbProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
}
这个类是实际处理操作的类,需要继承MapperTemplate,具体代码在**第四步**写。

第三步,在HsqldbMapper<T>中添加通用方法

这里以一个分页查询作为例子。 public interface HsqldbMapper { /** * 单表分页查询 * * @param object * @param offset * @param limit * @return */ @SelectProvider(type=HsqldbProvider.class,method = "dynamicSQL") List selectPage(@Param("entity") T object, @Param("offset") int offset, @Param("limit") int limit); }

返回结果为List,入参分别为查询条件和分页参数。在Mapper的接口方法中,当有多个入参的时候建议增加@Param注解,否则就得用param1,param2...来引用参数。

同时必须在方法上添加注解。查询使用SelectProvider,插入使用@InsertProvider,更新使用UpdateProvider,删除使用DeleteProvider。不同的Provider就相当于xml中不同的节点,如<select>,<insert>,<update>,<delete>。

因为这里是查询,所以要设置为SelectProvider,这4个Provider中的参数都一样,只有type和method。

type必须设置为实际执行方法的HasqldbProvider.class,method必须设置为"dynamicSQL"。

通用Mapper处理的时候会根据type反射HasqldbProvider查找方法,而Mybatis的处理机制要求method必须是type类中只有一个入参,且返回值为String的方法。"dynamicSQL"方法定义在MapperTemplate中,该方法如下:

public String dynamicSQL(Object record) {
return "dynamicSQL";
}
这个方法只是为了满足Mybatis的要求,没有任何实际的作用。

第四步,在HsqldbProvider中实现真正处理Sql的方法

在这里有一点要求,那就是HsqldbProvider处理HsqldbMapper<T>中的方法时,方法名必须一样,因为这里需要通过反射来获取对应的方法,方法名一致一方面是为了减少开发人员的配置,另一方面和接口对应看起来更清晰。

除了方法名必须一样外,入参必须是MappedStatement ms,除此之外返回值可以是void或者SqlNode之一。

这里先讲一下通用Mapper的实现原理。通用Mapper目前是通过拦截器在通用方法第一次执行的时候去修改MappedStatement对象的SqlSource属性。而且只会执行一次,以后就和正常的方法没有任何区别。

使用Provider注解的这个Mapper方法,Mybatis本身会处理成ProviderSqlSource(一个SqlSource的实现类),由于之前的配置,这个ProviderSqlSource种的SQL是上面代码中返回的"dynamicSQL"。这个SQL没有任何作用,如果不做任何修改,执行这个代码肯定会出错。所以在拦截器中拦截符合要求的接口方法,遇到ProviderSqlSource就通过反射调用如HsqldbProvider中的具体代码去修改原有的SqlSource。

最简单的处理Mybatis SQL的方法是什么?就是创建SqlNode,使用DynamicSqlSource,这种情况下我们不需要处理入参,不需要处理代码中的各种类型的参数映射。比执行SQL的方式容易很多。

有关这部分的内容建议查看通用Mapper的源码和Mybatis源码了解,如果不了解在这儿说多了反而会乱。

下面在HsqldbProvider中添加public SqlNode selectPage(MappedStatement ms)方法:

/**
* 分页查询
* @param ms
* @return
*/
public SqlNode selectPage(MappedStatement ms) {
Class<?> entityClass = getSelectReturnType(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);

List<SqlNode> sqlNodes = new ArrayList<SqlNode>();
//静态的sql部分:select column ... from table
sqlNodes.add(new StaticTextSqlNode("SELECT "
+ EntityHelper.getSelectColumns(entityClass)
+ " FROM "
+ tableName(entityClass)));
//获取全部列
List<EntityHelper.EntityColumn> columnList = EntityHelper.getColumns(entityClass);
List<SqlNode> ifNodes = new ArrayList<SqlNode>();
boolean first = true;
//对所有列循环,生成<if test="property!=null">[AND] column = #{property}</if>
for (EntityHelper.EntityColumn column : columnList) {
StaticTextSqlNode columnNode
= new StaticTextSqlNode((first ? "" : " AND ") + column.getColumn()
+ " = #{entity." + column.getProperty() + "} ");
if (column.getJavaType().equals(String.class)) {
ifNodes.add(new IfSqlNode(columnNode, "entity."+column.getProperty()
+ " != null and " + "entity."+column.getProperty() + " != '' "));
} else {
ifNodes.add(new IfSqlNode(columnNode, "entity."+column.getProperty() + " != null "));
}
first = false;
}
//将if添加到<where>
sqlNodes.add(new WhereSqlNode(ms.getConfiguration(), new MixedSqlNode(ifNodes)));
//处理分页
sqlNodes.add(new IfSqlNode(new StaticTextSqlNode(" LIMIT #{limit}"),"offset==0"));
sqlNodes.add(new IfSqlNode(new StaticTextSqlNode(" LIMIT #{limit} OFFSET #{offset} "),"offset>0"));
return new MixedSqlNode(sqlNodes);
}

注:对这段代码感觉吃力的,可以对比本页最下面**结构**部分XML形式的查看。

首先这段代码要实现的功能是这样,根据传入的实体类参数中不等于null(字符串也不等于'')的属性作为查询条件进行查询,根据分页参数进行分页。

先看这两行代码:

//获取实体类型
Class<?> entityClass = getSelectReturnType(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);

首先获取了实体类型,然后通过setResultType将返回值类型改为entityClass,就相当于resultType=entityClass。

这里为什么要修改呢?因为默认返回值是T,Java并不会自动处理成我们的实体类,默认情况下是Object,对于所有的查询来说,我们都需要手动设置返回值类型。

对于insert,update,delete来说,这些操作的返回值都是int,所以不需要修改返回结果类型。

之后从List<SqlNode> sqlNodes = new ArrayList<SqlNode>();代码开始拼写SQL,首先是SELECT查询头,在EntityHelper.getSelectColumns(entityClass)中还处理了别名的情况。

然后获取所有的列,对列循环创建<if entity.property!=null>column = #{entity.property}</if>节点。最后把这些if节点组成的List放到一个<where>节点中。

这一段使用属性时用的是 entity. + 属性名,entity来自哪儿?来自我们前面接口定义处的Param("entity")注解,后面的两个分页参数也是。如果你用过Mybatis,相信你能明白。

之后在<where>节点后添加分页参数,当offset==0时和offset>0时的分页代码不同。

最后封装成一个MixedSqlNode返回。

返回后通用Mapper是怎么处理的,这里贴下源码:

SqlNode sqlNode = (SqlNode) method.invoke(this, ms);
DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(ms.getConfiguration(), sqlNode);
setSqlSource(ms, dynamicSqlSource);
返回SqlNode后创建了DynamicSqlSource,然后修改了ms原来的SqlSource。

第五步,配置通用Mapper接口到拦截器插件中

<plugins>
<plugin interceptor="com.github.abel533.mapper.MapperInterceptor">
<!--================================================-->
<!--可配置参数说明(一般无需修改)-->
<!--================================================-->
<!--UUID生成策略-->
<!--配置UUID生成策略需要使用OGNL表达式-->
<!--默认值32位长度:@java.util.UUID@randomUUID().toString().replace("-", "")-->
<!--<property name="UUID" value="@java.util.UUID@randomUUID().toString()"/>-->
<!--主键自增回写方法,默认值MYSQL,详细说明请看文档-->
<property name="IDENTITY" value="HSQLDB"/>
<!--序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle-->
<!--可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName,PropertyName-->
<property name="seqFormat" value="{0}.nextval"/>
<!--主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)-->
<!--<property name="ORDER" value="AFTER"/>-->
<!--支持Map类型的实体类,自动将大写下划线的Key转换为驼峰式-->
<!--这个处理使得通用Mapper可以支持Map类型的实体(实体中的字段必须按常规方式定义,否则无法反射获得列)-->
<property name="cameHumpMap" value="true"/>
<!--通用Mapper接口,多个用逗号隔开-->
<property name="mappers" value="com.github.abel533.mapper.Mapper,com.github.abel533.hsqldb.HsqldbMapper"/>
</plugin>
</plugins>
这里主要是**mappers**参数:

<property name="mappers" value="com.github.abel533.mapper.Mapper,com.github.abel533.hsqldb.HsqldbMapper"/>
多个通用Mapper可以用逗号隔开。

测试

接下来编写代码进行测试。

public interface CountryMapper extends Mapper<Country>,HsqldbMapper<Country> {
}
在CountryMapper上增加继承HsqldbMapper<Country>。

编写如下的测试:

@Test
public void testDynamicSelectPage() {
SqlSession sqlSession = MybatisHelper.getSqlSession();
try {
CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
//带查询条件的分页查询
Country country = new Country();
country.setCountrycode("US");
List<Country> countryList = mapper.selectPage(country, 0, 10);
//查询总数
Assert.assertEquals(1, countryList.size());
//空参数的查询
countryList = mapper.selectPage(new Country(), 100, 10);
Assert.assertEquals(10, countryList.size());
} finally {
sqlSession.close();
}
}
测试输出日志如下:

DEBUG [main] - ==> Preparing: SELECT ID,COUNTRYNAME,COUNTRYCODE FROM COUNTRY WHERE COUNTRYCODE = ? LIMIT ?
DEBUG [main] - ==> Parameters: US(String), 10(Integer)
TRACE [main] - <== Columns: ID, COUNTRYNAME, COUNTRYCODE
TRACE [main] - <== Row: 174, United States of America, US
DEBUG [main] - <== Total: 1
DEBUG [main] - ==> Preparing: SELECT ID,COUNTRYNAME,COUNTRYCODE FROM COUNTRY LIMIT ? OFFSET ?
DEBUG [main] - ==> Parameters: 10(Integer), 100(Integer)
TRACE [main] - <== Columns: ID, COUNTRYNAME, COUNTRYCODE
TRACE [main] - <== Row: 101, Maldives, MV
TRACE [main] - <== Row: 102, Mali, ML
TRACE [main] - <== Row: 103, Malta, MT
TRACE [main] - <== Row: 104, Mauritius, MU
TRACE [main] - <== Row: 105, Mexico, MX
TRACE [main] - <== Row: 106, Moldova, Republic of, MD
TRACE [main] - <== Row: 107, Monaco, MC
TRACE [main] - <== Row: 108, Mongolia, MN
TRACE [main] - <== Row: 109, Montserrat Is, MS
TRACE [main] - <== Row: 110, Morocco, MA
DEBUG [main] - <== Total: 10
测试没有任何问题。

这里在来点很容易实现的一个功能。上面代码中:

countryList = mapper.selectPage(new Country(), 100, 10);
传入一个没有设置任何属性的Country的时候会查询全部结果。有些人会觉得传入一个空的对象不如传入一个null。我们修改测试代码看看结果。

执行测试代码后抛出异常:

Caused by: org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, "id")
为什么会异常呢,因为我们上面代码中直接引用的entity.property,在引用前并没有判断entity != null,因而导致了这里的问题。

我们修改HsqldbProvider中的selectPage方法,将最后几行代码进行修改,原来的代码:

//将if添加到<where>
sqlNodes.add(new WhereSqlNode(ms.getConfiguration(), new MixedSqlNode(ifNodes)));
修改后:

//增加entity!=null判断
IfSqlNode ifSqlNode = new IfSqlNode(new MixedSqlNode(ifNodes),"entity!=null");
//将if添加到<where>
sqlNodes.add(new WhereSqlNode(ms.getConfiguration(), ifSqlNode));
之后再进行测试就没有问题了。

Ⅱ 使用mybatis框架中mapper Mysql Sql语句错误

1.SQL语句可以通过xml或者java代码代码生成对应的SQL语句或者通过诸如@Select注解来定义,都是ok的,官方推荐用xml,因为其表达能力更强,官方也做了更好的适配。
2.在语句与方法映射这一步,可以使用<mapper> 标签进行注册,然后通过sqlSession的一系列方法使用之,也可以自己定义一个接口,在接口中定义方法来实现映射。
关于第一部分:

Ⅲ 请教Mybatis中如何在程序中获取Mapper中定义的SQL语句

<mappernamespace="AccountMapper">
<updateid="updateLoginTime"parameterType="int">
<![CDATA[
updatesys_accountsetlogin_date=now(),updatedate=now()whereid=#{accountId}
]]>
</update>
</mapper>

举例如上面的xml定义的Mapper,在代码中可以通过AccountMapper.updateLoginTime获取到update sys_account set login_date = now(), updatedate = now() where id = #{accountId}这行sql

Ⅳ 用mybatis开发sql怎么写

用Spring框架,在applicationContext.xml文件里配置以下内容:
<!-- 读取db.properties文件的内容 -->
<util:properties id = "jdbc" location = "classpath:db.properties"/>
<!-- 配置DataSource -->
<bean id = "ds" class = "org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value = "#{jdbc.driver}"/>
<property name="url" value = "#{jdbc.url}"/>
<property name="username" value = "#{jdbc.user}"/>
<property name="password" value = "#{jdbc.pwd}"/>
</bean>

<!-- 配置SqlSessionFactoryBean -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入DataSource -->
<property name="dataSource" ref="ds"/>
<!-- 注入映射文件的位置信息 -->
<property name="mapperLocations" value="classpath:com/tarena/oss/entity/*.xml"/>
</bean>

<!--
配置MapperSourceConfigurer:
扫描制定包下面所有的类,
创建符合Mapp接口要求的对象,
并且会将创建好的对象放到spring容器里面
-->
<bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入要扫描的包名 -->
<property name="basePackage" value = "com.tarena.oss."/>

</bean>
其中,要导入的包有:
mybatis-3.2.5.jar
mybatis-spring-1.2.2.jar
写好实体类之后,在创建一个mapper.xml文件。
注:实体类的属性名一定要和表的字段名一致。在mapper.xml映射文件里写sql语句。格式为:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

<mapper namespace="的路径名">

<!--
查询。
parameterType:如果返回值是一个整数,标准用法是java.lang.Integer,
可以简写为"int"。
-->
<select id = "和里面的方法名一致" parameterType="参数类型"
resultType="com.tarena.oss.entity.Admin">
查询的sql语句
</select>
<!--
使用resultMap来解决实体类的属性名,与表的字段名不一致的情况。
type属性: 实体类的名字。
property属性: 实体类的属性名。
column属性: 表的字段名。
注:如果属性名与字段名一样,就不用写了。
-->
</mapper>
其他语句在<mapper></mapper>里写,方法和select一样。

希望可以帮到你!

Ⅳ 这段sql怎么变成mapper.xml中的sql (mysql)

这段sql变成mapper.xml中的sql,把sql语句放在<select></select>标签里面就可以了
但是标签里面的 id 要写你的方法名,返回值写返回类型的全限定名,根据你的实体类写
如下:
<select id="" resultType="">
select * from sys_en_dic_type a
left join sys_en_dic b
on a.id=b.dic_id
</select>
不懂的可以继续追问,望采纳

Ⅵ 声明sql语句块与引用sql语句块分别是哪些标签

SQL
映射XML
文件是所有sql语句放置的地方。需要定义一个workspace,一般定义为对应的接口类的路径。写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如:
?
1
2
3
4
5
6
<mappers>
<mapper
resource="com/liming/manager/data/mappers/UserMapper.xml"
/>
<mapper
resource="com/liming/manager/data/mappers/StudentMapper.xml"
/>
<mapper
resource="com/liming/manager/data/mappers/ClassMapper.xml"
/>
<mapper
resource="com/liming/manager/data/mappers/TeacherMapper.xml"
/>
</mappers>
当Java接口与XML文件在一个相对路径下时,可以不在myBatis配置文件的mappers中声明。
SQL
映射XML
文件一些初级的元素:
(1).
cache

配置给定模式的缓存
(2).
cache-ref

从别的模式中引用一个缓存
(3).
resultMap

这是最复杂而却强大的一个元素了,它描述如何从结果集中加载对象
(4).
sql

一个可以被其他语句复用的SQL

(5).
insert

映射INSERT
语句
(6).
update

映射UPDATE
语句
(7).
delete

映射DELEETE
语句

Ⅶ 为什么会报错,sql语句在mapper.xml里的写法有什么不同吗

mybatis的sqlmap是xml格式的文件,你的代码里出现了小于号,而小于号是xml的组成部分,要用CDATA包裹住才不报错。
示例代码:
<select id="selectMonth" parameterType="java.util.HashMap" resultType="com.bilysice.chemicalPark.entity.ReFactor">
select
rf.item_id as itemId
, rf.device_id as deviceId
, rf.station_id as stationId
, rf.seq_date as seqDate
, rf.average_value averageValue
from re_factor rf
<where>
<if test=" itemId !=null">and rf.item_id = #{itemId}</if>
<if test=" deviceId !=null">and rf.device_id = #{deviceId}</if>
<if test=" station_id !=null">
and rf.station_id in
<foreach item="s" collection="stationIds" index="index" open="(" separator="," close=")">
#{s}
</foreach>
</if>
<if test=" stationId !=null">and rf.station_id = #{stationId}</if>
<if test=" srhTimeBegin !=null">and rf.seq_date <![CDATA[>=]]> #{srhTimeBegin}</if>
<if test=" srhTimeEnd !=null">and rf.seq_date <![CDATA[<]]> #{srhTimeEnd}</if>
</where>
</select>

Ⅷ mybatis中的mapper.xml中 sql语句

是的
如果你的对象字段和数据库字段不对应
你的xml文件上面应该有对象和数据库字段映射的配置resultMap

Ⅸ mybatis 动态sql语句用配置mapper吗

你这样写不行 返回类型必须是指定的java 类型 例如 java.lang.String 或者返回 map 然后使用反射 在把你的数据 写在 entity 里面

Ⅹ sql数据库代码写在哪里

在sql新建了个数据库的时候,再点击,刚新建的数据库,点击右边结构旁边的SQL,出现“在数据库XXXX 运行SQL 查询:”
把代码写进去就行了!