我的mapper加sql就抱什么sqlsessionfactory的错误
你的build()方法里的参数传错了把,下面是SqlSessionFactoryBuilder使用示例:
1
2
3
String resource="SqlMapperxml"
Reader reader=ResourcesgetResourceAsReader(resource);
SqlSessionFactoryBuilder sqlSessionFactory=new SqlSessionFactoryBuilder()build(reader);
如何开发自己的通用Mapper
HsqldbMapper实例
第一步,创建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=HsqldbProviderclass,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必须设置为实际执行方法的HasqldbProviderclass,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
sqlNodesadd(new StaticTextSqlNode("SELECT "
+ EntityHelpergetSelectColumns(entityClass)
+ " FROM "
+ tableName(entityClass)));
//获取全部列
List<EntityHelperEntityColumn> columnList = EntityHelpergetColumns(entityClass);
List<SqlNode> ifNodes = new ArrayList<SqlNode>();
boolean first = true;
//对所有列循环,生成<if test="property!=null">[AND] column = #{property}</if>
for (EntityHelperEntityColumn column : columnList) {
StaticTextSqlNode columnNode
= new StaticTextSqlNode((first "" : " AND ") + columngetColumn()
+ " = #{entity" + columngetProperty() + "} ");
if (columngetJavaType()equals(Stringclass)) {
ifNodesadd(new IfSqlNode(columnNode, "entity"+columngetProperty()
+ " != null and " + "entity"+columngetProperty() + " != '' "));
} else {
ifNodesadd(new IfSqlNode(columnNode, "entity"+columngetProperty() + " != null "));
}
first = false;
}
//将if添加到<where>
sqlNodesadd(new WhereSqlNode(msgetConfiguration(), new MixedSqlNode(ifNodes)));
//处理分页
sqlNodesadd(new IfSqlNode(new StaticTextSqlNode(" LIMIT #{limit}"),"offset==0"));
sqlNodesadd(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查询头,在EntityHelpergetSelectColumns(entityClass)中还处理了别名的情况。
然后获取所有的列,对列循环创建<if
entityproperty!=null>column = #{entityproperty}</if>节点。最后把这些if节点组成的List放到一个<where>节点中。
这一段使用属性时用的是 entity
+ 属性名,entity来自哪儿?来自我们前面接口定义处的Param("entity")注解,后面的两个分页参数也是。如果你用过Mybatis,相信你能明白。
之后在<where>节点后添加分页参数,当offset==0时和offset>0时的分页代码不同。
最后封装成一个MixedSqlNode返回。
返回后通用Mapper是怎么处理的,这里贴下源码:
SqlNode sqlNode = (SqlNode) methodinvoke(this, ms);
DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(msgetConfiguration(), sqlNode);
setSqlSource(ms, dynamicSqlSource);
返回SqlNode后创建了DynamicSqlSource,然后修改了ms原来的SqlSource。
第五步,配置通用Mapper接口到拦截器插件中
<plugins>
<plugin interceptor="comgithubabel533mapperMapperInterceptor">
<!--================================================-->
<!--可配置参数说明(一般无需修改)-->
<!--================================================-->
<!--UUID生成策略-->
<!--配置UUID生成策略需要使用OGNL表达式-->
<!--默认值32位长度:@javautilUUID@randomUUID()toString()replace("-", "")-->
<!--<property name="UUID" value="@javautilUUID@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="comgithubabel533mapperMapper,comgithubabel533hsqldbHsqldbMapper"/>
</plugin>
</plugins>
这里主要是mappers参数:
<property name="mappers" value="comgithubabel533mapperMapper,comgithubabel533hsqldbHsqldbMapper"/>
多个通用Mapper可以用逗号隔开。
测试
接下来编写代码进行测试。
public interface CountryMapper extends Mapper<Country>,HsqldbMapper<Country> {
}
在CountryMapper上增加继承HsqldbMapper<Country>。
编写如下的测试:
@Test
public void testDynamicSelectPage() {
SqlSession sqlSession = MybatisHelpergetSqlSession();
try {
CountryMapper mapper = sqlSessiongetMapper(CountryMapperclass);
//带查询条件的分页查询
Country country = new Country();
countrysetCountrycode("US");
List<Country> countryList = mapperselectPage(country, 0, 10);
//查询总数
AssertassertEquals(1, countryListsize());
//空参数的查询
countryList = mapperselectPage(new Country(), 100, 10);
AssertassertEquals(10, countryListsize());
} finally {
sqlSessionclose();
}
}
不支持,JPA的那些个注解或XML配置主要是针对ORM的,MyBatis严格来说不算ORM,它是把SQL映射成Object,不是把数据库表及其关系映射成Object,所以很难用JPA来进行标注。
无法连接到数据引擎的原因主要是你的服务没有开。右键单击我的电脑-----管理-----服务----找到sql的启动项(也可以是你自己的软件引擎),右键单击,选择-启动,等启动后,将你自己开的软件全部关掉,重新打开就可以了
以上就是关于我的mapper加sql就抱什么sqlsessionfactory的错误全部的内容,包括:我的mapper加sql就抱什么sqlsessionfactory的错误、如何开发自己的通用Mapper、通用mapper支持oracle数据库吗等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)