- 浏览: 70810 次
- 性别:
- 来自: 重庆
文章分类
最新评论
-
lizhenlzlz:
对我有用,谢谢
xstream简介(bean与xml转换工具) -
zhdi0:
myBatisDaoSupport 这个类没有呢
mybatis使用心得 -
yubenjie:
不错,学习了
mybatis使用心得 -
javaerman:
你好,用你给的地址没有下载下来,也给我发一份你的代码吧。jav ...
mybatis使用心得 -
lxw_it:
也发我一份吧,8659837@qq.com.谢了!
mybatis使用心得
一、mybatis版本
个人建议使用:
在mybatis3.1.1中优化了批量处理的效率
在底层statementHandle中提供了更加灵活的扩展性
主要是体现在插件,拦截器能做的,能够获取到的参数更多的方面
二、与spring集合的配置
这里对配置进行一下说明
mapperLocations: 通过正则表达式,支持mybatis动态扫描添加mapper不用像ibatis,用一个还要蛋疼滴添加一个include
typeHandlersPackage: 由于mybatis默认入参如果为空,又没有指定jdbcType时会抛出异常,在这里通过配置一些默认的类型空值插入的handle,以便处理mybatis的默认类型为空的情况
例如NullAbleStringTypeHandle通过实现当String字符串中为null是调用ps.setString(i,null)其他常用类型雷同
failFast:开启后将在启动时检查设定的parameterMap,resultMap是否存在,是否合法。个人建议设置为true,这样可以尽快定位解决问题。不然在调用过程中发现错误,会影响问题定位。
myBatisExceptionTranslator:用以支持spring的异常转换,通过配置该translatro可以将mybatis异常转换为spring中定义的DataAccessException
三、mybatis的批量处理功能,
由于在3.1.1升级后,可直接通过batchExcutor实现具体的批量执行。在该excutor中会重用上一次相同的prepareStatement。
具体实现这里贴一个:
这里的实现写得稍微复杂一些,
主要是,针对有些情况如果其中某条失败,还想后续数据能够继续成功提交的情况进行支持。
四、数据库物理分页,这个网上的文章也比较多,这里也提一下。在前人的基础上,我的物理分页类实现为:
五、jpa注解的支持,mybatis本来优势就在于其sql可控,
个人不太倾向用太多的注解,mybatis的resultMap已经在ibatis基础上改进了很多,已经非常好用了,个人倾向于,利用表生成对应的model
然后根据实际业务将model改写,如需要oneToOne manyToOne时,添加jpa注解,调整bean属性命名后,根据model直接生成,dao,service,daoImpl,sqlMap,以及单元测试类
这个我现在有一个初步实现:
已经可以用了,大家可以一起使用一下,如果有问题,可以在这里回帖,我再进行逐步优化:
具体代码请在github上下载,建议使用eclipse版本为spring的sts
sqlMap后来考虑重用statemen有关null处已经进行调整,将于明天更新于github
有兴趣的可以从github下载相关代码:
https://github.com/txteam/tx-core/tree/1.0.x
这里贴一下自动生成的代码:
个人建议使用:
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.1.1</version> </dependency>
在mybatis3.1.1中优化了批量处理的效率
在底层statementHandle中提供了更加灵活的扩展性
主要是体现在插件,拦截器能做的,能够获取到的参数更多的方面
二、与spring集合的配置
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="datasource"></property> <property name="configLocation" value="classpath:context/mybatis-config.xml"></property> <property name="mapperLocations" value="classpath*:/com/tx/demo/**/*SqlMap.xml" /> <property name="typeHandlersPackage" value="com.tx.core.mybatis.handler"></property> <property name="failFast" value="true"></property> <property name="plugins"> <array> <bean class="com.tx.core.mybatis.interceptor.PagedDiclectStatementHandlerInterceptor"> <property name="dialect"> <bean class="org.hibernate.dialect.PostgreSQLDialect"></bean> </property> </bean> </array> </property> </bean> <bean id="myBatisExceptionTranslator" class="org.mybatis.spring.MyBatisExceptionTranslator"> <property name="dataSource"> <ref bean="datasource"></ref> </property> </bean> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg> <constructor-arg name="executorType" ref="SIMPLE"></constructor-arg> <constructor-arg name="exceptionTranslator" ref="myBatisExceptionTranslator"></constructor-arg> </bean> <bean id="myBatisDaoSupport" class="com.tx.core.mybatis.support.MyBatisDaoSupport"> <property name="sqlSessionTemplate"> <ref bean="sqlSessionTemplate"/> </property> </bean>
这里对配置进行一下说明
mapperLocations: 通过正则表达式,支持mybatis动态扫描添加mapper不用像ibatis,用一个还要蛋疼滴添加一个include
typeHandlersPackage: 由于mybatis默认入参如果为空,又没有指定jdbcType时会抛出异常,在这里通过配置一些默认的类型空值插入的handle,以便处理mybatis的默认类型为空的情况
例如NullAbleStringTypeHandle通过实现当String字符串中为null是调用ps.setString(i,null)其他常用类型雷同
failFast:开启后将在启动时检查设定的parameterMap,resultMap是否存在,是否合法。个人建议设置为true,这样可以尽快定位解决问题。不然在调用过程中发现错误,会影响问题定位。
myBatisExceptionTranslator:用以支持spring的异常转换,通过配置该translatro可以将mybatis异常转换为spring中定义的DataAccessException
三、mybatis的批量处理功能,
由于在3.1.1升级后,可直接通过batchExcutor实现具体的批量执行。在该excutor中会重用上一次相同的prepareStatement。
具体实现这里贴一个:
/** * 批量插入数据 <br/> * 1、数据批量插入,默认一次提交100条,当发生异常后继续提交异常行以后的数据,待集合全部进行提交后返回批量处理结果<br/> * 2、数据批量插入,如果需要回滚,当发生异常后,数据库异常即向外抛出,不会进行至全部执行后再抛出异常 <br/> * <功能详细描述> * * @param statement * @param objectCollection * @param isRollback * @return [参数说明] * * @return BatchResult<T> [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ public BatchResult batchInsert(String statement, List<?> objectList, boolean isStopWhenFlushHappenedException) { return batchInsert(statement, objectList, defaultDoFlushSize, isStopWhenFlushHappenedException); } /** * 批量插入数据 * * @param statement * @param objectList * 对象列表 * @param doFlushSize * @param isStopWhenFlushHappenedException * 当在flush发生异常时是否停止,如果在调用insert时抛出的异常,不在此设置影响范围内 * @return void [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ // 批量插入 public BatchResult batchInsert(String statement, List<?> objectList, int doFlushSize, boolean isStopWhenFlushHappenedException) { BatchResult result = new BatchResult(); if (CollectionUtils.isEmpty(objectList)) { return result; } if (doFlushSize <= 0) { doFlushSize = defaultDoFlushSize; } //设置总条数 result.setTotalNum(objectList.size()); //从当前环境中根据connection生成批量提交的sqlSession SqlSession sqlSession = this.sqlSessionTemplate.getSqlSessionFactory() .openSession(ExecutorType.BATCH); try { // 本次flush的列表开始行行索引 int startFlushRowIndex = 0; for (int index = 0; index < objectList.size(); index++) { // 插入对象 insertForBatch(sqlSession, statement, objectList.get(index), null); if ((index > 0 && index % doFlushSize == 0) || index == objectList.size() - 1) { try { List<org.apache.ibatis.executor.BatchResult> test = flushBatchStatements(sqlSession); System.out.println(test); startFlushRowIndex = index + 1; } catch (Exception ex) { if (!(ex.getCause() instanceof BatchExecutorException) || isStopWhenFlushHappenedException) { DataAccessException translated = this.sqlSessionTemplate.getPersistenceExceptionTranslator() .translateExceptionIfPossible((PersistenceException) ex); throw translated; } BatchExecutorException e = (BatchExecutorException) ex.getCause(); // 如果为忽略错误异常则记录警告日志即可,无需打印堆栈,如果需要堆栈,需将日志级别配置为debug logger.warn("batchInsert hanppend Exception:{},the exception be igorned.", ex.toString()); if (logger.isDebugEnabled()) { logger.debug(ex.toString(), ex); } // 获取错误行数,由于错误行发生的地方 int errorRownumIndex = startFlushRowIndex + e.getSuccessfulBatchResults().size(); result.addErrorInfoWhenException(objectList.get(index), errorRownumIndex, ex); //将行索引调整为错误行的行号,即从发生错误的行后面一行继续执行 index = errorRownumIndex; startFlushRowIndex = errorRownumIndex + 1; } } } } finally { sqlSession.close(); } return result; }
这里的实现写得稍微复杂一些,
主要是,针对有些情况如果其中某条失败,还想后续数据能够继续成功提交的情况进行支持。
四、数据库物理分页,这个网上的文章也比较多,这里也提一下。在前人的基础上,我的物理分页类实现为:
<coding-3 lang="as"> /* * 描 述: <描述> * 修 改 人: PengQingyang * 修改时间: 2012-11-5 * <修改描述:> */ package com.tx.core.mybatis.interceptor; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Statement; import java.util.Properties; import org.apache.ibatis.executor.statement.PreparedStatementHandler; import org.apache.ibatis.executor.statement.RoutingStatementHandler; import org.apache.ibatis.executor.statement.SimpleStatementHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.RowBounds; import org.hibernate.dialect.Dialect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * <数据库分页容器处理器> * <功能详细描述> * * @author PengQingyang * @version [版本号, 2012-11-5] * @see [相关类/方法] * @since [产品/模块版本] */ @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }), @Signature(type = StatementHandler.class, method = "parameterize", args = { Statement.class }) }) public class PagedDiclectStatementHandlerInterceptor implements Interceptor { private Logger logger = LoggerFactory.getLogger(PagedDiclectStatementHandlerInterceptor.class); private Dialect dialect; /** * 物理分页插件拦截 * @param invocation * @return * @throws Throwable */ public Object intercept(Invocation invocation) throws Throwable { Method m = invocation.getMethod(); if ("prepare".equals(m.getName())) { return prepare(invocation); } else if ("parameterize".equals(m.getName())) { return parameterize(invocation); } return invocation.proceed(); } /** * @param target * @return */ public Object plugin(Object target) { return Plugin.wrap(target, this); } /** * @param properties */ public void setProperties(Properties properties) { } /** * 拦截prepare修改分页 * <功能详细描述> * @param invocation * @return * @throws Throwable [参数说明] * * @return Object [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ private Object prepare(Invocation invocation) throws Throwable { if (!(invocation.getTarget() instanceof RoutingStatementHandler)) { return invocation.proceed(); } //提取statement RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject(statementHandler); StatementHandler statement = (StatementHandler) metaStatementHandler.getValue("delegate"); //如果不为两种statement则不继续进行处理 if (!(statement instanceof SimpleStatementHandler) && !(statement instanceof PreparedStatementHandler)) { return invocation.proceed(); } RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds"); //根据rowBounds判断是否需要进行物理分页 if (rowBounds == null || rowBounds.equals(RowBounds.DEFAULT) || (rowBounds.getOffset() <= RowBounds.NO_ROW_OFFSET && rowBounds.getLimit() == RowBounds.NO_ROW_LIMIT)) { return invocation.proceed(); } //进行处理 BoundSql boundSql = statementHandler.getBoundSql(); String sql = boundSql.getSql(); String limitSql = dialect.getLimitString(sql, rowBounds.getOffset(), rowBounds.getLimit()); if (statement instanceof SimpleStatementHandler) { limitSql.replaceAll("rownum <= ?", "rownum <= " + rowBounds.getLimit()); limitSql.replaceAll("rownum_ > ?", "rownum_ > " + rowBounds.getOffset()); } //如果为PreparedStatementHandler则无需替换即可 metaStatementHandler.setValue("delegate.boundSql.sql",limitSql); if (logger.isDebugEnabled()) { logger.debug("生成分页SQL : " + boundSql.getSql()); } return invocation.proceed(); } /** * 设置分页参数 * <功能详细描述> * @param invocation * @return * @throws Throwable [参数说明] * * @return Object [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ private Object parameterize(Invocation invocation) throws Throwable { //先执行系统默认的参数设置 Object returnObj = invocation.proceed(); //提取statement RoutingStatementHandler routingStatementHandler = (RoutingStatementHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject(routingStatementHandler); StatementHandler statementHandler = (StatementHandler) metaStatementHandler.getValue("delegate"); //如果不为两种statement则不继续进行处理 if (!(statementHandler instanceof PreparedStatementHandler)) { return returnObj; } RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds"); //根据rowBounds判断是否需要进行物理分页 if (rowBounds == null || rowBounds.equals(RowBounds.DEFAULT) || (rowBounds.getOffset() <= RowBounds.NO_ROW_OFFSET && rowBounds.getLimit() == RowBounds.NO_ROW_LIMIT)) { return returnObj; } //提取参数设置statement Statement statement = (Statement) invocation.getArgs()[0]; if (!(statement instanceof PreparedStatement)) { //如果对应statement不为PreparedStatement则直接返回 return returnObj; } //设置分页的参数 PreparedStatement ps = (PreparedStatement) statement; int parameterSize = statementHandler.getBoundSql().getParameterMappings().size(); if(rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET || rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT){ ps.setInt(parameterSize + 1, rowBounds.getLimit()); parameterSize++; if(rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET){ ps.setInt(parameterSize + 1, rowBounds.getOffset()); } } //替换rowBounds metaStatementHandler.setValue("delegate.rowBounds", RowBounds.DEFAULT); return returnObj; } /** * @return 返回 dialect */ public Dialect getDialect() { return dialect; } /** * @param 对dialect进行赋值 */ public void setDialect(Dialect dialect) { this.dialect = dialect; } } </coding>
五、jpa注解的支持,mybatis本来优势就在于其sql可控,
个人不太倾向用太多的注解,mybatis的resultMap已经在ibatis基础上改进了很多,已经非常好用了,个人倾向于,利用表生成对应的model
然后根据实际业务将model改写,如需要oneToOne manyToOne时,添加jpa注解,调整bean属性命名后,根据model直接生成,dao,service,daoImpl,sqlMap,以及单元测试类
这个我现在有一个初步实现:
已经可以用了,大家可以一起使用一下,如果有问题,可以在这里回帖,我再进行逐步优化:
具体代码请在github上下载,建议使用eclipse版本为spring的sts
sqlMap后来考虑重用statemen有关null处已经进行调整,将于明天更新于github
有兴趣的可以从github下载相关代码:
https://github.com/txteam/tx-core/tree/1.0.x
这里贴一下自动生成的代码:
public static void main(String[] args) throws Exception{ JpaEntityFreeMarkerGenerator g = new JpaEntityFreeMarkerGenerator(); g.generate(Demo.class, "d:/mybatis"); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="demo"> <!-- auto generate default resultMap --> <resultMap id="demoMap" type="com.tx.core.mybatis.data.Demo"> <result column="subDemo_id" property="subDemo.id"/> </resultMap> <!-- auto generate default find --> <select id="findDemo" parameterType="com.tx.core.mybatis.data.Demo" resultMap="demoMap"> SELECT TW.ID, TW.INTTEST, TW.BOOLEANTEST, TW.PASSOWRD, TW.ENDDATE, TW.ISBOOLEANOBJTEST, TW.LASTUPDATEDATE, TW.TESTBIGDECEIMAL, TW.INTEGERTEST, TW.EMAIL, TW.NEWNAME AS name, TW.SUBDEMO AS subDemo_id, TW.TESTINTEGER, TW.CREATEDATE FROM WD_DEMO TW WHERE <trim prefixOverrides="AND | OR"> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)"> AND TW.ID = #{id} </if> </trim> </select> <!-- auto generate default query --> <select id="queryDemo" parameterType="com.tx.core.mybatis.data.Demo" resultMap="demoMap"> SELECT TW.ID, TW.INTTEST, TW.BOOLEANTEST, TW.PASSOWRD, TW.ENDDATE, TW.ISBOOLEANOBJTEST, TW.LASTUPDATEDATE, TW.TESTBIGDECEIMAL, TW.INTEGERTEST, TW.EMAIL, TW.NEWNAME AS name, TW.SUBDEMO AS subDemo_id, TW.TESTINTEGER, TW.CREATEDATE FROM WD_DEMO TW <trim prefix="WHERE" prefixOverrides="AND | OR"> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)"> AND TW.ID = #{id} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(intTest)"> AND TW.INTTEST = #{intTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(booleanTest)"> AND TW.BOOLEANTEST = #{booleanTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(passowrd)"> AND TW.PASSOWRD = #{passowrd} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(endDate)"> AND TW.ENDDATE = #{endDate} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(isBooleanObjTest)"> AND TW.ISBOOLEANOBJTEST = #{isBooleanObjTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(lastUpdateDate)"> AND TW.LASTUPDATEDATE = #{lastUpdateDate} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testBigDeceimal)"> AND TW.TESTBIGDECEIMAL = #{testBigDeceimal} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(integerTest)"> AND TW.INTEGERTEST = #{integerTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(email)"> AND TW.EMAIL = #{email} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(name)"> AND TW.NEWNAME = #{name} </if> <if test="subDemo != null"> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(subDemo.id)"> AND TW.SUBDEMO = #{subDemo.id} </if> </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testInteger)"> AND TW.TESTINTEGER = #{testInteger} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(createDate)"> AND TW.CREATEDATE = #{createDate} </if> </trim> <choose> <when test="@com.tx.core.util.OgnlUtils@isNotEmpty(orderSql)"> ORDER BY #{orderSql} </when> <otherwise> <!-- //TODO:ADD DEFAULT ORDER COLUMN OR DONOTHING! --> </otherwise> </choose> </select> <!-- auto generate default count --> <select id="queryDemoCount" parameterType="com.tx.core.mybatis.data.Demo" resultType="java.lang.Integer"> SELECT COUNT(1) FROM WD_DEMO TW <trim prefix="WHERE" prefixOverrides="AND | OR"> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)"> AND TW.ID = #{id} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(intTest)"> AND TW.INTTEST = #{intTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(booleanTest)"> AND TW.BOOLEANTEST = #{booleanTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(passowrd)"> AND TW.PASSOWRD = #{passowrd} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(endDate)"> AND TW.ENDDATE = #{endDate} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(isBooleanObjTest)"> AND TW.ISBOOLEANOBJTEST = #{isBooleanObjTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(lastUpdateDate)"> AND TW.LASTUPDATEDATE = #{lastUpdateDate} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testBigDeceimal)"> AND TW.TESTBIGDECEIMAL = #{testBigDeceimal} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(integerTest)"> AND TW.INTEGERTEST = #{integerTest} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(email)"> AND TW.EMAIL = #{email} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(name)"> AND TW.NEWNAME = #{name} </if> <if test="subDemo != null"> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(subDemo.id)"> AND TW.SUBDEMO = #{subDemo.id} </if> </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testInteger)"> AND TW.TESTINTEGER = #{testInteger} </if> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(createDate)"> AND TW.CREATEDATE = #{createDate} </if> </trim> </select> <!-- auto generate default insert --> <insert id="insertDemo" parameterType="com.tx.core.mybatis.data.Demo"> INSERT INTO WD_DEMO ( ID, INTTEST, BOOLEANTEST, PASSOWRD, ENDDATE, ISBOOLEANOBJTEST, LASTUPDATEDATE, TESTBIGDECEIMAL, INTEGERTEST, EMAIL, NEWNAME, SUBDEMO, TESTINTEGER, CREATEDATE ) VALUES ( #{id}, #{intTest}, #{booleanTest}, #{passowrd}, #{endDate}, #{isBooleanObjTest}, #{lastUpdateDate}, #{testBigDeceimal}, #{integerTest}, #{email}, #{name}, <if test="subDemo != null"> #{subDemo.id}, </if> <if test="subDemo == null"> #{subDemo,javaType=java.lang.String}, </if> #{testInteger}, #{createDate} ) </insert> <!-- auto generate default delete --> <delete id="deleteDemo" parameterType="com.tx.core.mybatis.data.Demo"> DELETE FROM WD_DEMO TW WHERE <trim prefixOverrides="AND | OR"> <if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)"> AND TW.ID = #{id} </if> </trim> </delete> <!-- auto generate default update --> <update id="updateDemo" parameterType="java.util.Map"> UPDATE wd_demo TW <trim prefix="SET" suffixOverrides=","> <if test="_parameter.containsKey('intTest')"> INTTEST = #{intTest,javaType=int}, </if> <if test="_parameter.containsKey('booleanTest')"> BOOLEANTEST = #{booleanTest,javaType=boolean}, </if> <if test="_parameter.containsKey('passowrd')"> PASSOWRD = #{passowrd,javaType=java.lang.String}, </if> <if test="_parameter.containsKey('endDate')"> ENDDATE = #{endDate,javaType=java.sql.Date}, </if> <if test="_parameter.containsKey('isBooleanObjTest')"> ISBOOLEANOBJTEST = #{isBooleanObjTest,javaType=java.lang.Boolean}, </if> <if test="_parameter.containsKey('lastUpdateDate')"> LASTUPDATEDATE = #{lastUpdateDate,javaType=java.sql.Timestamp}, </if> <if test="_parameter.containsKey('testBigDeceimal')"> TESTBIGDECEIMAL = #{testBigDeceimal,javaType=java.math.BigDecimal}, </if> <if test="_parameter.containsKey('integerTest')"> INTEGERTEST = #{integerTest,javaType=java.lang.Integer}, </if> <if test="_parameter.containsKey('email')"> EMAIL = #{email,javaType=java.lang.String}, </if> <if test="_parameter.containsKey('name')"> NEWNAME = #{name,javaType=java.lang.String}, </if> <if test="_parameter.containsKey('subDemo')"> <if test="subDemo != null"> SUBDEMO = #{subDemo.id,javaType=java.lang.String}, </if> <if test="subDemo == null"> SUBDEMO = #{subDemo,javaType=java.lang.String}, </if> </if> <if test="_parameter.containsKey('testInteger')"> TESTINTEGER = #{testInteger,javaType=java.lang.Integer}, </if> <if test="_parameter.containsKey('createDate')"> CREATEDATE = #{createDate,javaType=java.util.Date}, </if> </trim> WHERE TW.ID = #{id} </update> </mapper> <!-- sqlMap生成描述: -->
/* * 描 述: <描述> * 修 改 人: * 修改时间: * <修改描述:> */ package com.tx.core.mybatis.service; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.tx.core.mybatis.dao.DemoDao; import com.tx.core.mybatis.model.Demo; import com.tx.core.exceptions.parameter.ParameterIsEmptyException; import com.tx.core.paged.model.PagedList; /** * Demo的业务层 * <功能详细描述> * * @author * @version [版本号, ] * @see [相关类/方法] * @since [产品/模块版本] */ @Component("demoService") public class DemoService { @SuppressWarnings("unused") private Logger logger = LoggerFactory.getLogger(DemoService.class); @SuppressWarnings("unused") //@Resource(name = "serviceLogger") private Logger serviceLogger; @Resource(name = "demoDao") private DemoDao demoDao; /** * 根据Id查询Demo实体 * 1、当id为empty时返回null * <功能详细描述> * @param id * @return [参数说明] * * @return Demo [返回类型说明] * @exception throws 可能存在数据库访问异常DataAccessException * @see [类、类#方法、类#成员] */ public Demo findDemoById(String id) { if (StringUtils.isEmpty(id)) { return null; } Demo condition = new Demo(); condition.setId(id); return this.demoDao.findDemo(condition); } /** * 根据Demo实体列表 * TODO:补充说明 * * <功能详细描述> * @return [参数说明] * * @return List<Demo> [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ public List<Demo> queryDemoList(/*TODO:自己定义条件*/) { //TODO:判断条件合法性 //TODO:生成查询条件 Map<String, Object> params = new HashMap(); //TODO:根据实际情况,填入排序字段等条件,根据是否需要排序,选择调用dao内方法 List<Demo> resList = this.demoDao.queryDemoList(params); return resList; } /** * 分页查询Demo实体列表 * TODO:补充说明 * * <功能详细描述> * @return [参数说明] * * @return List<Demo> [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ public PagedList<Demo> queryDemoPagedList(/*TODO:自己定义条件*/int pageIndex, int pageSize) { //TODO:判断条件合法性 //TODO:生成查询条件 Map<String, Object> params = new HashMap<String, Object>(); //TODO:根据实际情况,填入排序字段等条件,根据是否需要排序,选择调用dao内方法 PagedList<Demo> resPagedList = this.demoDao.queryDemoPagedList(params, pageIndex, pageSize); return resPagedList; } /** * 查询demo列表总条数 * TODO:补充说明 * <功能详细描述> * @return [参数说明] * * @return int [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ public int countDemo(/*TODO:自己定义条件*/){ //TODO:判断条件合法性 //TODO:生成查询条件 Map<String, Object> params = new HashMap<String, Object>(); //TODO:根据实际情况,填入排序字段等条件,根据是否需要排序,选择调用dao内方法 int res = this.demoDao.countDemo(params); return res; } /** * 将demo实例插入数据库中保存 * 1、如果demo为空时抛出参数为空异常 * 2、如果demo中部分必要参数为非法值时抛出参数不合法异常 * <功能详细描述> * @param demo [参数说明] * * @return void [返回类型说明] * @exception throws 可能存在数据库访问异常DataAccessException * @see [类、类#方法、类#成员] */ @Transactional public void insertDemo(Demo demo) { //TODO:验证参数是否合法,必填字段是否填写, //如果没有填写抛出parameterIsEmptyException, //如果有参数不合法ParameterIsInvalidException if (demo == null /*TODO:|| 其他参数验证*/) { throw new ParameterIsEmptyException( "DemoService.insertDemo demo isNull."); } this.demoDao.insertDemo(demo); } /** * 根据id删除demo实例 * 1、如果入参数为空,则抛出异常 * 2、执行删除后,将返回数据库中被影响的条数 * @param id * @return 返回删除的数据条数,<br/> * 有些业务场景,如果已经被别人删除同样也可以认为是成功的 * 这里讲通用生成的业务层代码定义为返回影响的条数 * @return int [返回类型说明] * @exception throws 可能存在数据库访问异常DataAccessException * @see [类、类#方法、类#成员] */ @Transactional public int deleteById(String id) { if (StringUtils.isEmpty(id)) { throw new ParameterIsEmptyException( "DemoService.deleteById id isEmpty."); } Demo condition = new Demo(); condition.setId(id); return this.demoDao.deleteDemo(condition); } /** * 根据id更新对象 * <功能详细描述> * @param demo * @return [参数说明] * * @return boolean [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ @Transactional public boolean updateById(Demo demo) { //TODO:验证参数是否合法,必填字段是否填写, //如果没有填写抛出parameterIsEmptyException, //如果有参数不合法ParameterIsInvalidException if (demo == null || StringUtils.isEmpty(demo.getId())) { throw new ParameterIsEmptyException( "DemoService.updateById demo or demo.id is empty."); } //TODO:生成需要更新字段的hashMap Map<String, Object> updateRowMap = new HashMap<String, Object>(); updateRowMap.put("id", demo.getId()); //TODO:需要更新的字段 updateRowMap.put("intTest", demo.getIntTest()); updateRowMap.put("booleanTest", demo.isBooleanTest()); updateRowMap.put("passowrd", demo.getPassowrd()); updateRowMap.put("endDate", demo.getEndDate()); updateRowMap.put("isBooleanObjTest", demo.getIsBooleanObjTest()); updateRowMap.put("lastUpdateDate", demo.getLastUpdateDate()); updateRowMap.put("testBigDeceimal", demo.getTestBigDeceimal()); updateRowMap.put("integerTest", demo.getIntegerTest()); updateRowMap.put("email", demo.getEmail()); updateRowMap.put("name", demo.getName()); //type:java.lang.String updateRowMap.put("subDemo", demo.getSubDemo()); updateRowMap.put("testInteger", demo.getTestInteger()); updateRowMap.put("createDate", demo.getCreateDate()); int updateRowCount = this.demoDao.updateDemo(updateRowMap); //TODO:如果需要大于1时,抛出异常并回滚,需要在这里修改 return updateRowCount >= 1; } }
/* * 描 述: <描述> * 修 改 人: * 修改时间: * <修改描述:> */ package com.tx.core.mybatis.dao.impl; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.springframework.stereotype.Component; import com.tx.core.mybatis.dao.DemoDao; import com.tx.core.mybatis.data.Demo; import com.tx.core.mybatis.model.Order; import com.tx.core.mybatis.support.MyBatisDaoSupport; import com.tx.core.paged.model.PagedList; /** * Demo持久层 * <功能详细描述> * * @author * @version [版本号, 2012-12-11] * @see [相关类/方法] * @since [产品/模块版本] */ @Component("demoDao") public class DemoDaoImpl implements DemoDao { @Resource(name = "myBatisDaoSupport") private MyBatisDaoSupport myBatisDaoSupport; /** * @param condition */ @Override public void insertDemo(Demo condition) { this.myBatisDaoSupport.insertUseUUID("demo.insertDemo", condition, "id"); } /** * @param condition * @return */ @Override public int deleteDemo(Demo condition) { return this.myBatisDaoSupport.delete("demo.deleteDemo", condition); } /** * @param condition * @return */ @Override public Demo findDemo(Demo condition) { return this.myBatisDaoSupport.<Demo> find("demo.findDemo", condition); } /** * @param params * @return */ @Override public List<Demo> queryDemoList(Map<String, Object> params) { return this.myBatisDaoSupport.<Demo> queryList("demo.queryDemo", params); } /** * @param params * @param orderList * @return */ @Override public List<Demo> queryDemoList(Map<String, Object> params, List<Order> orderList) { return this.myBatisDaoSupport.<Demo> queryList("demo.queryDemo", params, orderList); } /** * @param params * @return */ @Override public int countDemo(Map<String, Object> params) { return this.myBatisDaoSupport.<Integer> find("demo.queryDemoCount", params); } /** * @param params * @param pageIndex * @param pageSize * @return */ @Override public PagedList<Demo> queryDemoPagedList(Map<String, Object> params, int pageIndex, int pageSize) { return this.myBatisDaoSupport.<Demo> queryPagedList("demo.queryDemo", params, pageIndex, pageSize); } /** * @param params * @param pageIndex * @param pageSize * @param orderList * @return */ @Override public PagedList<Demo> queryDemoPagedList(Map<String, Object> params, int pageIndex, int pageSize, List<Order> orderList) { return this.myBatisDaoSupport.<Demo> queryPagedList("demo.queryDemo", params, pageIndex, pageSize, orderList); } /** * @param updateRowMap * @return */ @Override public int updateDemo(Map<String, Object> updateRowMap) { return this.myBatisDaoSupport.update("demo.updateDemo", updateRowMap); } }
评论
9 楼
zhdi0
2015-04-30
myBatisDaoSupport 这个类没有呢
8 楼
yubenjie
2015-01-09
不错,学习了
7 楼
javaerman
2014-08-18
你好,用你给的地址没有下载下来,也给我发一份你的代码吧。javaerman@163.com
6 楼
lxw_it
2014-08-18
也发我一份吧,8659837@qq.com.谢了!
5 楼
liu_haibo
2014-08-08
也发我一份吧,2951290398@qq.com.谢了!
4 楼
yangkexin
2014-07-24
也发我一份吧,yang_yan770@sohu.com.谢了!!
3 楼
woshizmy0910
2014-05-13
你好,git上的项目没有找到,能否把发一份您的项目到我的邮箱woshizmy0910@163.com
2 楼
icecookstar
2013-07-22
请问一下,批量插入的功能写在哪个类里面?
1 楼
zhaobing0816
2012-12-21
这个必须支持一下
相关推荐
在使用MyBatis时,我们需要理解其核心组件和工作原理,以便更好地进行数据库操作。 一、MyBatis核心配置文件 MyBatis的核心配置文件通常命名为`mybatis-config.xml`,它是整个MyBatis系统的总配置文件,包含了数据...
在使用 MyBatis 的原生接口开发时,虽然相对于其他高级封装如 MyBatis-Plus 或者 Spring Data JPA,可能会显得较为繁琐,但其核心优势在于灵活度和控制力度。下面将详细阐述 MyBatis 原生接口开发的关键步骤和注意...
- **性能优化**:虽然MyBatis提供了很多高级特性,但在实际使用中还需要根据具体情况进行性能优化,如合理设计SQL语句、使用缓存等。 总之,MyBatis作为一个轻量级的框架,不仅能够满足大部分项目的需求,而且在...
本篇文章将聚焦于MyBatis中的注解(Annotation)与XML配置的结合使用,旨在帮助开发者更深入地理解这一关键特性。 首先,MyBatis允许我们使用注解来简化Mapper接口的定义,无需编写XML映射文件。例如,我们可以在...
Spring_mybatis的小整合练习,可以测试着在线学习一下!
springboot配置文件模板:包括多环境开发布置,端口号配置,全局jackson配置,mysql数据库配置,oracle数据库配置,连接池配置,redis配置,redis链接池的配置,设置上传文件大小限制配置,全局格式化时间配置,https证书配置...
在描述中提到的博客链接(由于实际无法访问,这里仅做理论性分析),可能讲解了作者使用MyBatis的心得体会,可能包括最佳实践、常见问题及其解决方案。 标签中的“源码”意味着可能涉及到MyBatis的源代码解析,理解...
本教程专注于使用Spring、Spring MVC和MyBatis这三个关键组件进行实战教学。这三者构成了Java EE开发中的重要支柱,为开发者提供了强大的功能和灵活性。 Spring框架是Java EE开发的核心,它是一个全功能的容器,...
【描述】:虽然描述中并未给出具体信息,但根据“博文链接:https://java-lxm.iteye.com/blog/1208173”,我们可以推测该内容可能包含了博主对MyBatis的学习心得、使用技巧或者是源码解析。通常在这样的博文中,作者...
4. **社区参与**:加入 MyBatis 的社区或论坛,与其他开发者交流心得,分享经验。 5. **实战应用**:在真实的项目中使用 MyBatis,遇到问题及时寻求解决方案,不断积累实践经验。 通过上述介绍,我们可以看出 ...
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和...记得在学习过程中多做笔记,记录下自己的练习和心得,这将有助于巩固和深化对 MyBatis 的理解。
这个“Mybatis学习笔记”可能是某位开发者的学习心得或者是教程资料,通过阅读我们可以深入理解Mybatis的核心概念和用法。 Mybatis的主要特点包括: 1. **动态SQL**:Mybatis允许在映射文件中编写动态SQL,使得SQL...
### 实验设计报告心得与体会综合分析 #### 一、实验设计的重要性和前期准备 在进行任何实验之前,充分理解理论知识是至关重要的。实验不仅仅是简单地操作仪器或设备,而是建立在深厚理论基础上的实际应用过程。...
MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。在本项目中,MyBatis作为数据访问层,负责与数据库交互,执行SQL语句,...
在IT行业中,MyBatis是一个广泛使用的持久层框架,它允许开发者将对象关系映射(Object-Relational Mapping,ORM)以XML配置文件的方式进行定义,从而极大地简化了数据库操作。这篇“mybatis学习总结:对象关系映射...
**JFinal 使用心得与架构解析** JFinal 是一个基于 Java 的轻量级 Web 开发框架,它以 MVC(Model-View-Controller)架构为基础,强调“简洁高效”的设计理念,为开发者提供了一个快速开发项目的平台。在本文中,...
SSH(Spring、Struts、Hibernate)是Java Web开发的经典组合,这个压缩包中包含了一些关于Spring在实际使用过程中的心得和常见问题的解决方案。 首先,"spring的事务代理.txt"可能涉及到Spring的事务管理。Spring...
虽然Spring Data JDBC本身支持Mybatis,但在整合过程中需要遵守诸多规则,例如Mybatis上下文的参数管理、接口命名规范等,增加了学习和使用的难度。因此,我决定尝试独立实现一种简单的通用Mapper方案。 **一些尝试...
SSM(Spring + Spring MVC + MyBatis)框架作为Java开发中的黄金组合,为开发者提供了强大的技术支持和丰富的功能。本系列资料将带您从零基础开始,逐步掌握SSM的核心技术和最佳实践,助您在Java Web开发领域更上一...