我的mapper加sql就抱什么sqlsessionfactory的错误

我的mapper加sql就抱什么sqlsessionfactory的错误,第1张

我的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数据库吗等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9698537.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存