绿茶新标签和旧标签的新旧会计准则差异比较

mybatis支持多数据库切换 - topcat - ITeye技术网站
博客分类:
使用mybatis时都是用的sqlmapper来做的数据库到java对象的映射,因此在针对一些特定数据库方言使用时无法在多个数据库上切换。
解决方案:
通过定义environment的id来指定使用不同的数据库映射文件,如下
&!--WizRtf2Html Charset=0
&?xml version="1.0" encoding="UTF-8" ?& &!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"&&configuration&
&environments
default="mysql"&
&environment id="mysql"&
&transactionManager
type="JDBC"
&dataSource type="POOLED"&
&property name="driver" value="com.mysql.jdbc.Driver"
&property name="url" value="jdbc:mysql://localhost:3306/test"
&property name="username" value="root"
&property name="password" value="pwd"
&/dataSource&
&/environment&
&/environments&
resource="cn/dcr/mybatis/entity/UserMapper.xml"
&/mappers&&/configuration&
方法设置方言
private void
environmentsElement(XNode context) throws
Exception { if (context != null) {if (environment == null)
environment =
context.getStringAttribute("default");
}for (XNode child :
context.getChildren()) {
String id = child.getStringAttribute("id");
dialect = id.toLowerCase();//设置方言if (isSpecifiedEnvironment(id))
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
DataSourceFactory
dsFactory = dataSourceElement(child.evalNode("dataSource"));
Environment.Builder
environmentBuilder = new
Environment.Builder(id).transactionFactory(txFactory).dataSource(dsFactory.getDataSource());
configuration.setEnvironment(environmentBuilder.build());
修改mapperElement方法
private void
mapperElement(XNode parent) throws Exception
{ if (parent != null) {for (XNode child :
parent.getChildren()) {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
InputStream
inputSif (resource
!= null && url
== null) {if(dialect !=
resource = dialect
+ "/" +//从方言指定位置查找
ErrorContext.instance().resource(resource);
inputStream
Resources.getResourceAsStream(resource);
XMLMapperBuilder
mapperParser = new
XMLMapperBuilder(inputStream, configuration, resource,
configuration.getSqlFragments());
mapperParser.parse();
else if (url
!= null &&
resource == null) {if(dialect !=
url = dialect + "/" +//从方言指定位置查找
ErrorContext.instance().resource(url);
inputStream
Resources.getUrlAsStream(url);
XMLMapperBuilder
mapperParser = new
XMLMapperBuilder(inputStream, configuration, url,
configuration.getSqlFragments());
mapperParser.parse();
else {throw new
BuilderException("A mapper element may only specify a url or
resource, but not
继承org.apache.ibatis.session.SqlSessionFactoryBuilder类创建一个新类org.apache.ibatis.session.SqlSessionFactoryBuilderEx用来加载org.apache.ibatis.builder.xml.XMLConfigBuilderEx
覆盖父类中的build方法
public SqlSessionFactory build(InputStream
inputStream, String environment, Properties props) { try {
XMLConfigBuilderEx parser = new
XMLConfigBuilderEx(inputStream, environment,
Configuration config =
parser.parse();return
build(config);
} catch (Exception
ExceptionFactory.wrapException("Error building
SqlSession.", e);
ErrorContext.instance().reset();try
inputStream.close();
} catch (IOException e) {// Intentionally ignore. Prefer previous
调用org.apache.ibatis.builder.xml.XMLConfigBuilderEx来加载配置文件
自定义mybatis配置加载Bean在spring的配置文件中添加方言的配置让自定义Bean在加载mybatis的配置时可以使用不同的数据库映射文件,如下
id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBeanEx"&
name="dataSource"
ref="dataSource" /&
&property name="configLocation"
value="classpath:configuration.xml" /&
name="mapperLocations" value="classpath*:${jdbc.dialect}/mappers/*.xml"
/& &/bean&
${jdbc.dialect}在配置文件中设置,如mysql,那么spring会把mysql/mappers下的所有映射文件加载进来
以org.mybatis.spring.SqlSessionFactoryBean为蓝本创建org.mybatis.spring.SqlSessionFactoryBeanEx类
将成员变量
private SqlSessionFactoryBuilder
sqlSessionFactoryBuilder = new
SqlSessionFactoryBuilder();
private SqlSessionFactoryBuilderEx
sqlSessionFactoryBuilderEx = new
SqlSessionFactoryBuilderEx();
并去掉setSqlSessionFactoryBuilder方法添加setSqlSessionFactoryBuilderEx方法
覆盖buildSqlSessionFactory方法
protected SqlSessionFactory buildSqlSessionFactory()
throws IOException, IllegalAccessException,
InstantiationException { XMLConfigBuilderEx
xmlConfigBuilderEx;
Configuration
if (this.configLocation !=
null) {try
xmlConfigBuilderEx = new XMLConfigBuilderEx(this.configLocation.getInputStream(), null, this.configurationProperties);
configuration
= xmlConfigBuilderEx.parse();
} catch (Exception ex) {throw new
NestedIOException("Failed to parse config resource: "
+ this.configLocation, ex);
ErrorContext.instance().reset();
}if (this.logger.isDebugEnabled())
{this.logger.debug("Parsed configuration file: '" +
this.configLocation + "'");
} else {if (this.logger.isDebugEnabled())
{this.logger.debug("Property 'configLocation' not specified, using default MyBatis
Configuration");
configuration = new
Configuration();
}if (this.transactionFactory == null) {this.transactionFactory =
new SpringManagedTransactionFactory(this.dataSource);
Environment
environment = new
Environment(this.environment, this.transactionFactory, this.dataSource);
configuration.setEnvironment(environment);if (!ObjectUtils.isEmpty(this.mapperLocations)) {
Map&String, XNode&
sqlFragments = new
HashMap&String, XNode&();for (Resource mapperLocation : this.mapperLocations)
{if (mapperLocation == null) {continue;
}// MyBatis holds a Map using "resource" name as a
key.// If a mapper file is
loaded, it searches for a mapper// interface type.// If the type is found then it tries to load the mapper
file// again looking for
this://// String
xmlResource = type.getName().replace('.', '/') +// ".xml";//// So if a mapper
interface exists, resource cannot be an// absolute path.//
Otherwise MyBatis will throw an exception
because// it will load both a
mapper interface and the mapper xml file,// and throw an exception telling that a mapperStatement
cannot// be loaded
Sif (mapperLocation instanceof ClassPathResource)
path = ((ClassPathResource)
mapperLocation).getPath();
} else {//
this won't work if there is also a mapper interface
mapperLocation.toString();
XMLMapperBuilder
xmlMapperBuilder = new
XMLMapperBuilder(mapperLocation.getInputStream(), configuration, path,
sqlFragments);
xmlMapperBuilder.parse();
catch (Exception e)
{throw new NestedIOException("Failed to
parse mapping resource: '" + mapperLocation
ErrorContext.instance().reset();
}if (this.logger.isDebugEnabled())
{this.logger.debug("Parsed mapper
file: '" + mapperLocation + "'");
else {if (this.logger.isDebugEnabled())
{this.logger.debug("Property 'mapperLocations' was not specified, only MyBatis mapper
files specified in the config xml were
}return this.sqlSessionFactoryBuilderEx.build(configuration);
浏览 20950
浏览: 210975 次
来自: 湖北武汉
谢谢,这问题让我搞了一整天都快崩溃了。。。
让我搞了一个中午,刚开始以后是缓存问题,谢谢。。。
真的很苦B呀
没人关注你的技术,关注的是你的文采mybatis/ibatis直接执行sql语句 - 简约不简单 - ITeye技术网站
博客分类:
在项目中,使用的是mybatis3.0.5,但没有采用其提供的DAO层接口映射的策略,而且在进行多种属性联合查找时,需要底层提供通用的解决方案,所以需要mybatis直接执行sql语句,各个daoImpl均可调用,减少了在每个mybatis文件中配置符合当前对象的select查询。。
(在mybatis中,需要通过传递对象,在select中判断对象属性是否为空进行where语句的拼凑,对后期的维护工作带来不小的考验,所以采用直接执行sql策略)
先说一说配置时,遇到的异常:
&select id="findRecords" parameterType="String" resultMap="orderTypeResultMap"&
这样配置时,会出现:there no getter sql in java.lang.String 的异常
所以考虑:用一个适配器,将sql作为属性加入其中
&typeAlias alias="sqladapter" type="com.zj.logistics.util.SQLAdapter" /&
public class SQLAdapter {
public SQLAdapter(String sql) {
this.sql =
public String getSql() {
public void setSql(String sql) {
this.sql =
&select id="findRecords" parameterType="SQLAdapter" resultMap="orderTypeResultMap"&
注意,不要忘记在调用该select方法时,用new SqlAdapter("自己写的sql语句")作为参数哦。。。
想更深入了解,请浏览
浏览 12027
我自己实现了一个Esql, 比IBatis更加简单易用,不过在产品化上还差一步。
public EsqlDemoBean selectBeanByBean(Object params) {
return new Esql().selectFirst("selectByBean")
.params(params)
.returnType(EsqlDemoBean.class)
.execute();
[selectByBean]
SELECT A,B,C,D,E
FROM ESQL_TEST
WHERE A = #a#
AND C = #c#
示例代码在:/AL-WUHC2/n3r-core/blob/master/src/test/java/org/n3r/esql/demo/EsqlDemo.java示例SQL在:/AL-WUHC2/n3r-core/blob/master/src/test/resources/org/n3r/esql/demo/EsqlDemo.esql好的,有空研究下。。
楼主,你还别说,你这个思路我还真觉得挺新颖的,我一直想用mybatis,但是xml里写sql还真有些蛋疼这个问题我也是想了很久,除了必要的依赖对应关系以及查询条件不复杂的select写在了xml中,像 [where ... order by ... limit ... ] 还是自己维护比较方便。。另外,如果查询条件中有大于小于号,在xml中还得用转义符号。。
${sql} 改成#{sql}呢?那更不行啦。。MyBatis看到 #{}会认为你在给sql中的变量赋值,就像JDBC编程中给问号赋值一样(比如MyBatis会判断它的类型,并自动在前后加单引号)。而当MyBatis看到${}的时候会直接将之替换成变量的值而不做任何处理。
&select id="findRecords" parameterType="String" resultMap="orderTypeResultMap"& ${sql}&/select&这样配置时,会出现:there no getter sql in java.lang.String 的异常这是因为配置parameterType="String"有问题parameterType后跟具体类名或者是org.apache.ibatis.type.TypeAliasRegistry中注册的类型,你应该写parameterType="string"才对。你说的我也试过,也是不行的,同样还是抛there no getter sql in java.lang.String 的异常
你的sql应该不会被,mybatis缓存的你说的很可能是对的,按主键查询和外键之间的查询,还是按照mybatis的标准配置来进行,如果查询条件很多,而且又包含order by及分页数据,自己维护应该要容易一点,因为order by的数据需要用linkedmap,而查询条件用hashmap就够了。。所以我还是写了一个父类,让每个daoImpl去继承,在父类中写一个抽象方法帮助我们拼接sql语句。。
楼主是怎么处理参数的?有没有sql注入问题? sql参数是通过键值对的形式传递的,比如servlet接受到参数后,将参数放入map中,map.put("username","小")map.put("address","杭州")然后将数据传递至数据访问层,对map进行遍历,拼出where语句。。sql注入的问题没有考虑过,但由于是自己写的sql语句,肯定有方法能够检测,这还有待研究啊。。
SQL参数,预处理如何处理先?sql参数是通过键值对的形式传递的,比如servlet接受到参数后,将参数放入map中,map.put("username","小")map.put("address","杭州")然后将数据传递至数据访问层,对map进行遍历,拼出where语句。。
比如在下面这种情况下,可能只想些一条sql。&!--TeacherMapper接口中getById方法对应的SQL语句。 查询教师及其指导的学生的信息。由于教师、学生都有 id、name、gender等属性,因此给教师的字段都起了别名 --& &select id="getById" parameterType="int" resultMap="teacherResultMap"&
select t.id t_id, t.name t_name,
s.id,s.name
from i_teacher t,i_student s
and s.t_id = t.id
and t.id=#{id} &/select& &select id="getAll" resultMap="teacherResultMap"&
select t.id t_id, t.name t_name,
s.id,s.name
from i_teacher t,i_student s
and s.t_id = t.id &/select&你的这种写法没错,但是在项目中,尤其是类似于依赖对应关系(一对多,多对多)很多的情况下,这样的维护往往是令我们吃不消的。往往依靠mybatis提供的association和collection帮助我们维护。。在进行组合条件查询时,我们一般都会将select * from table [where ... order by ... limit ... ] 中 [...]写成通用方法,供每个daoImpl去引用
麻烦楼主把工程共享出来,谢谢嗯,过几天我整理一下。。
作者说的 是mybatis 运行期 获取xml中定义的 sql语句吧?拿到这个sql ,然后再动态进行各种拼接。是我们自己写一个sql语句,直接让mybatis执行select * from table [where ... order by ... limit ... ]在[...]中,我们可以自己在dao层通过抽象通用方法,拼接出来符合自己业务逻辑的条件。。
resultType="java.util.Map",返回一个Map对象也是可以的嗯,这要看我们写的sql语句返回的内容是什么了。。select * from ... 用map就不合适了。。
& 上一页 1
浏览: 171081 次
来自: 宁波
浏览量:7575
求楼主给个选择题答案不
厉害,还是楼主的方法管用。赞100个
梦想太丰满现实很骨感 写道找了好久,终于找到了。感谢博主!希望 ...
mraping 写道非常感谢!不客气Mybatis的两种写法。。。 - ITeye问答
在网上搜索Mybatis的教程,看到了2个:
1.http://wanqiufeng./132
这里会先定义一个UserMapper的Interface
然后使用的时候
UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUser("jun");
2.http://blog.csdn.net/weoln/article/details/5782750
这里就没有Interface
直接使用
Goods goods = (Goods)session.selectOne("com.oryx.mybatis.GoodsMapper.selectGoods",1);
看了论坛里关于是不是可以不写DAO的讨论,但只是稍微有点概念,但是具体Mybatis的原理还是没搞清楚。
第一种,如果mybatis本身的Mapper层就是一个接口的话,那么它的实现应该是xml文件了,这里的UserMapper userMapper =sqlSession.getMapper(UserMapper.class);算是什么?& 这个userMapper是谁的实现呢?& Mapper的还是用户自定义那个UserMapper的? 感觉像是UserMapper这个接口的,但是具体的sql访问(DaoImp)是谁来完成的呢? 感觉又是xml文件来完成的,所以就有点晕了。。。
用户自定义的接口和框架提供的借口到底是一种什么关系,框架又是怎么自动帮助用户自定义的接口实现其中的方法的?
能解释下这里面的原理么?& selectOne都做了哪些步骤?
采纳的答案
第一种,UserMapper userMapper =sqlSession.getMapper(UserMapper.class);得到了一个UserMapper的代理。核心是JDK的动态代理。你只要定义UserMapper这个接口的方法getUser就可以了,mybatis生成代理,也是实现UserMapper接口的,然后解析xml,调用SQL,返回结果给你。你自己则根本感觉不到代理的存在,感觉就是在调用UserMapper。
第二种,selectOne就是选择一条记录,解析xml里sql,把参数绑定上去,执行sql,最后把sql返回的结果填充到Goods对象里。内部实现都是jdbc啦,只不过不用你写这些琐碎的细节了,全有mubatis搞定。
底层代码里,第一种其实最后还是会调用第二种的selectOne的。
mapper& 接口方式,是mybatis3 中 基于接口形式。通过 xml 中与接口的 ID 映射关系,进行SQL 调用。
而 你说的& selectOne 是 mybatis 本身 以前基于JDBC 数据库模板操作的 一种方式。就像hibernate& session.save 之类的。不知道你是否明白
如果把现有的hibernate中的配置移植到spring中,是完全正常的
已解决问题
未解决问题mybatis+mysql如何批量执行多条语句 -
- ITeye技术网站
博客分类:
此处仅描述问题处理方法,关于mysql、mybatis的内容不在此赘述。
因为项目需要,需要在mybatis同个标签中执行多条sql语句。如下:
&insert id="insertUser" parameterType="com.test.model.User"&
insert into user (id,email,name,phone,status) values(#{id,jdbcType=INTEGER},#{email,jdbcType=VARCHAR},#{nick,jdbcType=VARCHAR},#{phone,jdbcType=VARCHAR},#{status,jdbcType=INTEGER});
delete from roleuser where userid=#{id,jdbcType=INTEGER};
&if test="roles != null and roles.size() != 0 "&
insert into roleuser (userid,roleid) values
&foreach collection="roles" item="roleId" separator="," close=";"&
(#{id,jdbcType=INTEGER},#{roleId,jdbcType=INTEGER})
&/foreach&
寻思着,在mysql中同时执行多条语句时,mysql是一条一条执行的。如果我一次性向mysql发送多条语句,它应该也会这么执行的。
我承认一开始想的太简单了,直接这样做的结果,是会在jdbc驱动层面报出语法错误异常,程序无法执行下去。
debug后发现,从mybatis拼装sql,到语句传入jdbc驱动,语句都是正常的,但是在mysql驱动验证sql合法性时,sql被截断,它认为一次性发过去的多条sql是不合法的。
看了网上很多说法,一说是mybatis本身不支持;一说是mysql驱动不支持。困扰很久,没能解决,后为了项目进度,暂时将sql分开执行了。
&insert id="insertUser" parameterType="com.test.model.User"&
insert into user (id,email,name,phone,status) values(#{id,jdbcType=INTEGER},#{email,jdbcType=VARCHAR},#{nick,jdbcType=VARCHAR},#{phone,jdbcType=VARCHAR},#{status,jdbcType=INTEGER});
&delete id="deleteUserById" parameterType="java.lang.Integer"&
delete from roleuser where userid=#{id,jdbcType=INTEGER};
但今天,有高人,跟我说,这样做不行,是因为你没有让mysql驱动开启批量执行sql的开关。
怎么开启呢?在拼装mysql链接的url时,为其加上allowMultiQueries参数,设置为true,如下:
jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/database?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
加了参数后,我又将mybatis配置文件改了回去,测试一下,执行成功。
这里记录一下,希望对看到的人,有所帮助。
浏览: 11951 次
来自: 杭州
生产场不能用, 会增加sql注入的风险
太赞了,我说那个地方配置不对呢,原来有这个设置

我要回帖

更多关于 陈旧绿茶 的文章

 

随机推荐