java写mapper的简单介绍
今天给各位分享java写mapper的知识,其中也会对进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、JAVA 生成mapper映射找不到方法,求解答
- 2、java mapper文件 怎么写
- 3、如何开发自己的通用Mapper
- 4、Java Web中的mapper,service,controller,model究竟分别是什么作用?
- 5、java中知道model层,怎么根据model层 写service层、impl层、mapper层
JAVA 生成mapper映射找不到方法,求解答
扫描xml文件的路径不对,你xml放在了mapping文件夹,你这里写的是mapper,看你目录结构 你这个文件夹里放的是java文件 俗称的dao层
java mapper文件 怎么写
mapper namespace="接口名连接"
select id="接口中方法一致:如getUserById" resultType="User返回值" parameterType="参数如:int"
select id,name,pwd from user where id=#{id}
/select
/mapper
如何开发自己的通用Mapper
如何开发自己的通用Mapper
要求
自己定义的通用Mapper必须包含泛型,例如MysqlMapperT。
自定义的通用Mapper接口中的方法需要有合适的注解。具体可以参考Mapper
需要继承MapperTemplate来实现具体的操作方法。
通用Mapper中的Provider一类的注解只能使用相同的type类型(这个类型就是第三个要实现的类。)。实际上method也都写的一样。
HsqldbMapper实例
第一步,创建HsqldbMapperT
public interface HsqldbMapperT {
}
这个接口就是我们定义的通用Mapper,具体的接口方法在**第三步**写。其他的Mapper可以继承这个HsqldbMapperT。
第二步,创建HsqldbProvider
public class HsqldbProvider extends MapperTemplate {
//继承父类的方法
public HsqldbProvider(Class? mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
}
这个类是实际处理操作的类,需要继承MapperTemplate,具体代码在**第四步**写。
第三步,在HsqldbMapperT中添加通用方法
这里以一个分页查询作为例子。 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处理HsqldbMapperT中的方法时,方法名必须一样,因为这里需要通过反射来获取对应的方法,方法名一致一方面是为了减少开发人员的配置,另一方面和接口对应看起来更清晰。
除了方法名必须一样外,入参必须是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);
ListSqlNode sqlNodes = new ArrayListSqlNode();
//静态的sql部分:select column ... from table
sqlNodes.add(new StaticTextSqlNode("SELECT "
+ EntityHelper.getSelectColumns(entityClass)
+ " FROM "
+ tableName(entityClass)));
//获取全部列
ListEntityHelper.EntityColumn columnList = EntityHelper.getColumns(entityClass);
ListSqlNode ifNodes = new ArrayListSqlNode();
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} "),"offset0"));
return new MixedSqlNode(sqlNodes);
}
注:对这段代码感觉吃力的,可以对比本页最下面**结构**部分XML形式的查看。
首先这段代码要实现的功能是这样,根据传入的实体类参数中不等于null(字符串也不等于'')的属性作为查询条件进行查询,根据分页参数进行分页。
先看这两行代码:
//获取实体类型
Class? entityClass = getSelectReturnType(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
首先获取了实体类型,然后通过setResultType将返回值类型改为entityClass,就相当于resultType=entityClass。
这里为什么要修改呢?因为默认返回值是T,Java并不会自动处理成我们的实体类,默认情况下是Object,对于所有的查询来说,我们都需要手动设置返回值类型。
对于insert,update,delete来说,这些操作的返回值都是int,所以不需要修改返回结果类型。
之后从ListSqlNode sqlNodes = new ArrayListSqlNode();代码开始拼写SQL,首先是SELECT查询头,在EntityHelper.getSelectColumns(entityClass)中还处理了别名的情况。
然后获取所有的列,对列循环创建if entity.property!=nullcolumn = #{entity.property}/if节点。最后把这些if节点组成的List放到一个where节点中。
这一段使用属性时用的是 entity. + 属性名,entity来自哪儿?来自我们前面接口定义处的Param("entity")注解,后面的两个分页参数也是。如果你用过Mybatis,相信你能明白。
之后在where节点后添加分页参数,当offset==0时和offset0时的分页代码不同。
最后封装成一个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可以用逗号隔开。
Java Web中的mapper,service,controller,model究竟分别是什么作用?
java web中mapper是对象持久化映射层,一般会继承ibatis或者mybatis servive是一些业务逻辑的处理层,controller是控制层,相当于mvc的c层,model是数据模型层相当于mvc的m层。
Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言。
Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编译、到处执行”的跨平台特性。
不过,每次的编译执行需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。但在 J2SE 1.4.2 发布后,Java 的执行速度有了大幅提升。
与传统程序不同,Sun 公司在推出 Java 之际就将其作为一种开放的技术。全球数以万计的 Java 开发公司被要求所设计的 Java 软件必须相互兼容。
“Java 语言靠群体的力量而非公司的力量”是 Sun 公司的口号之一,并获得了广大软件开发商的认同。这与微软公司所倡导的注重精英和封闭式的模式完全不同。
java中知道model层,怎么根据model层 写service层、impl层、mapper层
没有强制的固定格式。
只是编程习惯。
不过要注意的是,一般在service 层 做事物。
至于怎么写 明白一点:
从controller(action层 不知道你用什么框架)---service 层(包括接口层和实现层(impl))------mapper层(Dao 层)。
1:这其实是 业务需要+编程习惯决定的。 因为这样分层,分模块开发,可扩展。逻辑思维清楚,这个你开发中可以体会到。
2:也就是说,你不用service 层 直接把所有东西写在一个方法里他照样可以实现功能。 但是这样不利于扩展,不利于维护。所以他们这样分层开发最好。框架这样设计是有道理的。
java写mapper的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、java写mapper的信息别忘了在本站进行查找喔。