這iBATIS的老大愛折騰,搬來搬去,看陳述的那些理由,我唯一的感覺就是:他厭倦了ASF的官僚作風。 對用戶影響很小,開源協(xié)議也沒變,還是最寬松的Apache 2.0,Google的網(wǎng)絡(luò)也比Apache快點。 不過MyBatis這個名字可不如iBATIS,讓人還以為是iBATIS的定制項目,比如MyEclipse和Eclipse。
相關(guān)推薦: ibator改造之返回數(shù)據(jù)庫注釋和數(shù)據(jù)庫分頁 ibatis的ibatorForEclipse的安裝與配置和ibator的錯誤日志查看 Ibator優(yōu)化版代碼生成過程 Ibator支持分頁的plugin mybatis (Ibatis ibator) generator - 1 mysql 分頁插件(page/paging/pagination plugin) 基于Struts2+Spring+iBatis的web應(yīng)用最佳實踐系列之五(分頁篇) ibator改造之返回數(shù)據(jù)庫注釋和數(shù)據(jù)庫分頁 推薦群組: struts2 更多相關(guān)推薦 iBATIS 首先聲明:該文章 參照了 http://www.iteye.com/topic/674839 ?? matychen ? 的文章 , 修改了一下 ibator 的工作方式,實際分頁的原理還是一樣的 , 支持 oracle,mysql?? , 如果涉及侵犯matychen的利益,請告知,我立即刪除 ? /** ? * ? * @author coffeesweet ? * ? */ Ibator 支持分頁的 plugin 式的開發(fā)步驟 ? 1: 所涉及到修改的類列表 : org.apache.ibatis.ibator.generator.ibatis2.sqlmap.elements 目錄下所有的類里給 attribute 屬性的 id 修改成如下 : FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable(); answer.addAttribute(new Attribute("id", table.getSqlMapNamespace() + "."+XmlConstants.INSERT_STATEMENT_ID)); ? 其他修改和添加的類 org.apache.ibatis.ibator.generator.ibatis2.sqlmap.elements---OraclePaginationHeadGenerator ?? org.apache.ibatis.ibator.generator.ibatis2.sqlmap.elements---OraclePaginationTailGenerator ?? org.apache.ibatis.ibator.generator.ibatis2.sqlmap.elements---MysqlPaginationLimitGenerator ?? org.apache.ibatis.ibator.generator.ibatis2.model---ExampleGenerator org.apache.ibatis.ibator.api.dom.java---FullyQualifiedJavaType ? ? org.apache.ibatis.ibator.api.dom.xml.XmlElement 添加了四個方法,主要用于對 xxxx_SqlMap.xml 的元素刪除和修改 ? 這個是添加的 plugin 類 org.apache.ibatis.ibator.plugins.PaginationPlugin ? 以上所有修改的類搜索 “ 增加開始 ” 或者 “ 增加結(jié)束 ” 就能找到修改的地方 ? 2: 示例 ibatorConfig.xml 文件 ? 一定要注意該 xml 的元素順序 ? 子元素的 第一個 位置 ibatorContext 的子元素順序是 (property*, ibatorPlugin*, commentGenerator?, jdbcConnection, javaTypeResolver?, ? javaModelGenerator, sqlMapGenerator, daoGenerator?, table+) 所以需要注意 ibatorPlugin 的位置,還有,如果有多個 plugin 的話,加入第一個的 validate 失敗,那么余下的所有 plugin 都不執(zhí)行了 ? 還要注意 ibatorPlugin 的兩個必要屬性 < property name = "enablePagination" value = "true" /> ???? ?? < property name = "dbType" value = "oracle" /> ? 示例 ibatorConfig.xml xml version = "1.0" encoding = "UTF-8" ?> < ibatorConfiguration > ? ??? < classPathEntry location = "oracle驅(qū)動的本地絕對路徑" /> ??? < ibatorContext id = "context1" targetRuntime = "Ibatis2Java5" > ??? ??? ???? ???? < ibatorPlugin type = "org.apache.ibatis.ibator.plugins.PaginationPlugin" > ???? ?? < property name = "enablePagination" value = "true" /> ???? ?? < property name = "dbType" value = "oracle" /> ???? ibatorPlugin > ???? ???? ?????? < jdbcConnection driverClass = "oracle.jdbc.driver.OracleDriver" ?????????? connectionURL = "jdbc:oracle:thin:@*.*.*.*:1521:**" userId = "**" ?????????? password = "**" /> ? ?????? < javaTypeResolver > ?????????? < property name = "forceBigDecimals" value = "false" /> ?????? javaTypeResolver > ? ? ?????? < javaModelGenerator targetPackage = "com.mydomain.model" ?????????? targetProject = "src" > ?????????? < property name = "enableSubPackages" value = "false" /> ?????????? < property name = "trimStrings" value = "false" /> ?????? javaModelGenerator > ? ?????? < sqlMapGenerator targetPackage = "com.mydomain.xml" ?????????? targetProject = "src" > ?????????? < property name = "enableSubPackages" value = "false" /> ?????? sqlMapGenerator > ? ?????? < daoGenerator type = "SPRING" targetPackage = "com.mydomain.dao" ?????????? targetProject = "src" > ?????????? < property name = "enableSubPackages" value = "false" /> ?????? daoGenerator > ? ? ?????? < table tableName = "CC_TEST1" domainObjectName = "Customer" > ?????????? ?????? table > ?????? ??????? ?????? ??? ibatorContext > ibatorConfiguration > ? 3: 以下是 ibator 的 java 啟動模式,用來測試 package org.apache.ibatis.ibator.test; import java.io.File; import java.util.ArrayList; import java.util.List; import org.apache.ibatis.ibator.api.Ibator; import org.apache.ibatis.ibator.config.IbatorConfiguration; import org.apache.ibatis.ibator.config.xml.IbatorConfigurationParser; import org.apache.ibatis.ibator.internal.DefaultShellCallback; public class IbatorRunTest { public static void main(String...strings){ try{ List warnings = new ArrayList(); boolean overwrite = true; File configFile = new File(ClassLoader.getSystemResource("ibatorConfig.xml").getFile()); // File configFile = new File("ibatorConfig.xml"); IbatorConfigurationParser cp = new IbatorConfigurationParser(warnings); // for(String warning:warnings){ // System.out.println("1---:"+warning); // } IbatorConfiguration config = cp.parseIbatorConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); Ibator ibator = new Ibator(config, callback, warnings); ibator.generate(null); for(String warning:warnings){ System.out.println("2---:"+warning); } }catch(Exception ex){ ex.printStackTrace(); } } } ? ? ? 4:附件是ibator的修改后的源碼(包括spring的lib)和jar包,以及測試case ? 源碼里的有關(guān)數(shù)據(jù)連接信息的東西請自行修改 測試用到了spring ibator.jar可直接拿到工程中使用 ? ? ? ? ? ? ? ? ? ? ?
相關(guān)推薦: 數(shù)據(jù)庫水平切分的實現(xiàn)原理解析 關(guān)于ibatis進行物理游標分頁 數(shù)據(jù)庫分切設(shè)計何必糾結(jié)于hibernate shard模式,應(yīng)該簡單化了 [] 通過ibatis實現(xiàn)輕量級的水平切分(已更新,ibatis原生api也可以實現(xiàn)sharding) 通過ibatis實現(xiàn)輕量級的水平切分(已更新,ibatis原生api也可以實現(xiàn)sharding) Ibatis實現(xiàn)分表 數(shù)據(jù)庫分庫分表(sharding)系列(一) 拆分實施策略和示例演示 數(shù)據(jù)庫水平切分的原理探討、設(shè)計思路--數(shù)據(jù)庫分庫,分表,集群,負載均衡器... 推薦群組: lucene愛好者 更多相關(guān)推薦 iBATIS 最近想在自己的項目里實現(xiàn)DB sharding功能,正好前段時間研究過ibatis的源碼于是就在ibatis的基礎(chǔ)上進行了一些修改。另一方面也是為了練練手。這個sharding的實現(xiàn)主要是基于我項目中的需求實現(xiàn)的可能有很多考慮不周的地方,希望各位大牛拍磚。如果有人感興趣愿意一起來發(fā)展這個項目,本人也非常歡迎各位的加入。Shardbatis是在mybatis 2.3.5代碼的基礎(chǔ)上進行一些擴展實現(xiàn)數(shù)據(jù)水平切分功能。 數(shù)據(jù)的水平切分包括多數(shù)據(jù)庫的切分和多表的數(shù)據(jù)切分。目前shardbatis已經(jīng)實現(xiàn)了單數(shù)據(jù)庫的數(shù)據(jù)多表水平切分 mybatis2.3.5的核心類圖(包含了spring對ibatis的封裝SqlMapClientTemplate)如下(其他版本的ibatis的類圖有略微不同) 改造后的類圖 從這兩張圖上可以看出shardbatis里新增了接口SqlMapShardingExt,SqlMapShardingExt中具體的方法如下 public interface SqlMapShardingExt extends SqlMapExecutor{ /** * 帶有sharding功能的insert * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ Object insertWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的insert * @param id * @param groups * @return * @throws SQLException */ Object insertWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的update * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ int updateWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的update * @param id * @param groups * @return * @throws SQLException */ int updateWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的delete * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ int deleteWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的delete * @param id * @param groups * @return * @throws SQLException */ int deleteWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的單記錄查詢 * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ Object queryForObjectWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的單記錄查詢 * @param id * @param groups * @return * @throws SQLException */ Object queryForObjectWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的單記錄查詢 * @param id * @param parameterObject * @param resultObject * @param groups * @return * @throws SQLException */ Object queryForObjectWithSharding(String id, Object parameterObject, Object resultObject, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的查詢 * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的查詢 * @param id * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的查詢 * @param id * @param parameterObject * @param skip * @param max * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, Object parameterObject, int skip, int max, ShardingFactorGroup... groups) throws SQLException; /** * 帶有sharding功能的查詢 * @param id * @param skip * @param max * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, int skip, int max, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param parameterObject * @param rowHandler * @param groups * @throws SQLException */ void queryWithRowHandlerWithSharding(String id, Object parameterObject, RowHandler rowHandler, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param rowHandler * @param groups * @throws SQLException */ void queryWithRowHandlerWithSharding(String id, RowHandler rowHandler, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param parameterObject * @param keyProp * @param groups * @return * @throws SQLException */ Map queryForMapWithSharding(String id, Object parameterObject, String keyProp, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param parameterObject * @param keyProp * @param valueProp * @param groups * @return * @throws SQLException */ Map queryForMapWithSharding(String id, Object parameterObject, String keyProp, String valueProp, ShardingFactorGroup... groups) throws SQLException; 通過SqlMapClientImpl和SqlMapSessionImpl對SqlMapShardingExt的實現(xiàn)是的ibatis具有了DB sharding的功能,iBATIS會自動根據(jù)配置的或者是編碼的sharding策略將原始的sql語句轉(zhuǎn)變?yōu)閷?yīng)目標表名的sql。 下面看一下如何在iBATIS中配置和使用sharding功能 1.配置sharding策略。在sql-map-config.xml中添加如下配置 這里再通過實例簡單介紹一下使用DefaultShardingStrategy時對sql的convert結(jié)果 比如sqlmap中定義的原始sql為: SELECT EMPLOYEEIDNO FROM mytable WHERE SALARY >= 50000 那經(jīng)過convert后的結(jié)果將可能是 SELECT EMPLOYEEIDNO FROM mytable_1 WHERE SALARY >= 50000 又例如原始sql為 SELECT a.* FROM ANTIQUES a,ANTIQUEOWNERS b, mytable c where a.id=b.id and b.id=c.id convert的結(jié)果可能為 SELECT a.* FROM ANTIQUES_0 AS a, ANTIQUEOWNERS_1 AS b, mytable_1 AS c WHERE a.id = b.id AND b.id = c.id 開始使用sharding api public class SqlMapClientTest { SqlMapClient sqlMapper; @Before public void init() { Reader reader; try { reader = Resources.getResourceAsReader("sql-map-config.xml"); sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader); reader.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Test public void testSharding() throws Exception { Map param = new HashMap(); param.put("cnt", "ttt"); ShardingFactorGroup g = new ShardingFactorGroup();//ShardingFactorGroup為切分策略提供必要參數(shù) g.setTableName("App_Test");//設(shè)置為哪張表配置切分策略 g.setParam(new Integer(123));//設(shè)置為切分策略提供參數(shù) //這里還可以通過g.setShardingStrategy(...)來設(shè)置切分策略 //通過API配置的切分策略可以覆蓋xml里配置的App_Test表的切分策略 Integer count = (Integer) sqlMapper.queryForObjectWithSharding( "AppTest.select_paging_count_by_map", param, g); Assert.assertEquals(count.toString(), "0"); } @Test public void testUpdate() throws SQLException { ShardingFactorGroup g = new ShardingFactorGroup(); g.setTableName("App_Test"); g.setParam(new Integer(123)); String cnt = "testUpdate" + System.currentTimeMillis(); AppTest at1 = new AppTest(); at1.setCnt(cnt); Integer id = (Integer) sqlMapper.insertWithSharding( "AppTest.insert_h2", at1, g); AppTest parameterObject = new AppTest(); parameterObject.setCnt(cnt); AppTest ret = (AppTest) sqlMapper.queryForObjectWithSharding( "AppTest.select_by_condition", parameterObject, g); Assert.assertEquals(ret.getId().toString(), id.toString()); ret.setCnt("NEW_CONTENT"); Integer count = sqlMapper.updateWithSharding("AppTest.update", ret, g); Assert.assertEquals(count.toString(), "1"); count = (Integer) sqlMapper.queryForObjectWithSharding( "AppTest.select_paging_count", ret, g); Assert.assertEquals(count.toString(), "1"); } @Test public void testDelete() throws SQLException { ShardingFactorGroup g = new ShardingFactorGroup(); g.setTableName("App_Test"); g.setParam(new Integer(123)); String cnt = "testDelete" + System.currentTimeMillis(); AppTest at1 = new AppTest(); at1.setCnt(cnt); Integer id = (Integer) sqlMapper.insertWithSharding( "AppTest.insert_h2", at1, g); AppTest parameterObject = new AppTest(); parameterObject.setCnt(cnt); AppTest ret = (AppTest) sqlMapper.queryForObjectWithSharding( "AppTest.select_by_condition", parameterObject, g); Assert.assertEquals(ret.getId().toString(), id.toString()); Integer row = sqlMapper.deleteWithSharding("AppTest.delete", ret, g); Assert.assertEquals(row.toString(), "1"); } } 實現(xiàn)自己的sharding策略,只要實現(xiàn)一個簡單的接口即可 public interface ShardingStrategy { /** * 計算得到新的表名 * @param baseTableName 邏輯表名 * @param params 為sharding邏輯提供必要參數(shù) * @return */ public String getTargetTableName(String baseTableName,Object params); } Since 0.9.1使用ibatis原生api也可以支持sharding功能 select count(*) from app_test where cnt=#cnt# 下面開始編碼 AppTest param=new AppTest(); param.setTestId(2); param.setCnt("testShardingWithConfig"); Integer count=(Integer)sqlMapper.queryForObject("AppTest.select_count_native",param);//和使用原生的ibatis API沒有區(qū)別 最終執(zhí)行的SQL可能是如下樣式 select count(*) from app_test_0 where cnt=? 關(guān)于shardbatis在spring中的使用方法,以及一些使用注意事項和性能測試結(jié)果請大家移步到項目主頁 http://code.google.com/p/shardbatis/ 上查看
相關(guān)推薦: 大家覺得現(xiàn)在搞iPhone的軟件開發(fā)有前途(錢途)嗎? 手機safari的AJAX開發(fā)(包括iPhone) 盤點免費文件網(wǎng)絡(luò)同步、備份工具 ios 開源的電子書閱讀器項目 直接拿來用!最火的iOS開源項目 OpenDigg iOS開源項目月報201704 iOS開源系列——完整開源項目 推薦群組: iphone,ipod touch開發(fā) 更多相關(guān)推薦 iOS TwitterFon is a simple, clean, easy to use, and super fast Twitter client for your iPhone and iPod Touch.The URL :http://twitterfon.net/ You can download source codes from svn repository http://naan.net/svn/trunk/TwitterFon
我沒用過UITabBar,但是看這個功能應(yīng)該可以用在一個view上加custom的button實現(xiàn)的
IBatis 要強于hiberante1.項目一般數(shù)據(jù)庫明確,不需要支持多數(shù)據(jù)庫,用hibernate 也不表示能完全兼容所有數(shù)據(jù)庫的所有select 語法(函數(shù)) 2.IBatis 的2員表達式 優(yōu)于使用 hibernate QBC 3.開發(fā)速度取決于開發(fā)人員的水平 而不于ibatis 和 hibernate(雖然可以生成.java .hbm.xml) 4.
agapple 寫道 LZ還可以考慮另一種思路,需要客戶端指定Entry的主鍵Key,每次update操作,清空有包含該key的相關(guān)cache數(shù)據(jù)即可。 目前似乎是在服務(wù)端攔截select 類型的query 或取參數(shù)來得到key,不知道你說的客戶端如何指定entry的主鍵key.
相關(guān)推薦: 使用Atomikos Transactions Essentials實現(xiàn)多數(shù)據(jù)源JTA分布式事務(wù) Spring中事物管理一二 Spring配置一個事務(wù)中多個數(shù)據(jù)源 spring mybatis atomikos分布式事務(wù) 【分布式】springboot + mybatis + JTA + Atomikos 實現(xiàn)多數(shù)據(jù)源的分布式事務(wù)管理 spring+mybatis+atomikos 實現(xiàn)JTA事務(wù) springboot實現(xiàn)mybatis分布式事務(wù)(atomikos) spring boot+Mybatis+mysql+atomikos+jta實現(xiàn)多數(shù)據(jù)源分布式事務(wù)
推薦群組: struts2
更多相關(guān)推薦
iBATIS
最近弄一個框架,使用spring3.0.5+mybatis3.0.5,需要訪問多庫,要應(yīng)用分布式事務(wù)JTA,這是用atomikos 3.70版本,并把配置做一下記錄。
配置多個數(shù)據(jù)源
?
SELECT 1 SELECT 1 ?
?
配置mybatis的SessionFactory
?
?
? 這里使用的是SessionFactory,不是 org.springframework.orm.ibatis.SqlMapClientFactoryBean,在mybatis3中用 SqlMapClientFactoryBean匯報 com.ibatis.common.xml.NodeletException ?異常。
?
configLocation 對應(yīng)的mybatis配置,跟平時配置一樣。
?事務(wù)這塊用spring管理atomikos
true ?
Mapper的管理及注入
?
atomikos的配置jta.properties,該文件放在應(yīng)用classpath下面
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory com.atomikos.icatch.console_file_name = tm.out com.atomikos.icatch.log_base_name = tmlog com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm com.atomikos.icatch.console_log_level=WARN ?
這幾基本配置完畢,需要jar包
atomikos-util.jar
transactions.jar
transactions-jta.jar
transactions-jdbc-deprecated.jar
mybatis.jar
mybatis-spring.jar
cglib.2.2.2.jar
spring的jar包
?
在Service中,調(diào)用事務(wù)的方法不能try。。。catch事務(wù)的方法,否者不能回滾
如下帶面就會出現(xiàn)不會滾問題
try{ userMapper.addUser(user); roleMapper.addRole(role); }catch(Exception){ } ?參考文章?http://www.iteye.com/topic/122700
?
Missing:---------- 1) javax.jms:jms:jar:1.1 Try downloading the file manually from: http://java.sun.com/products/jms/docs.html Then, install it using the command: mvn install:install-file -DgroupId=javax.jms -DartifactId=jms -Dversion=1.1 -Dpackaging=jar -Dfile=/path/to/file Alternatively, if you host your own repository you can deploy the file there: mvn deploy:deploy-file -DgroupId=javax.jms -DartifactId=jms -Dversion=1.1 -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id] Path to dependency: 1) com.alibaba.cobar:cobar-client:jar:1.0.3 2) log4j:log4j:jar:1.2.15 3) javax.jms:jms:jar:1.1 ---------- 1 required artifact is missing. for artifact: com.alibaba.cobar:cobar-client:jar:1.0.3
基本寫完了,還有一些小地方和不明朗的地方,比如validateParameter方法,ExecuteListener接口,稍后補充上吧。 望大家來拍拍轉(zhuǎn)吧
Mybatis已經(jīng)全面支持了!類似struts2對OGNL的操作. 樓主可以嘗試下.可以寫類似 ...... foreach很有用,在解決集合到sql轉(zhuǎn)換的問題上很給力! 比如 in()
相關(guān)推薦: Extjs3綜合應(yīng)用(待續(xù)v4...初版) Mybatis3.0查詢,保存,更新,刪除數(shù)據(jù)。 summercool-ddl框架簡介 (二) MyBaits中Insert至動態(tài)表名及foreach使用 在ibatis中使用oracle insert all 函數(shù) MyBatis動態(tài)sql_foreach下foreach批量插入兩種方式 mybatis中foreach的用法(轉(zhuǎn)) 推薦群組: struts2 更多相關(guān)推薦 iBATIS ? 下面是一個簡單的使用動態(tài)表名和 foreach 使用的簡單配置 insert into nwh.tt_${suffix}(a,b) values (#{obj[order]},#{obj[name]}) ${suffix} ?"${}" 只做簡單的替換 #{ obj [order]}"#{}"會做處理 ? ? 對應(yīng)的數(shù)據(jù)結(jié)構(gòu)如下面代碼表示: List> list = new ArrayList>(); Map map= new HashMap(); map.put("order", "123"); map.put("name", "miyong"); Map map2= new HashMap(); map2.put("order", "1234"); map2.put("name", "miyong"); list.add(map); list.add(map2); Map param = new HashMap(); param.put("suffix", "20110710"); param.put("list", list); ? ? 對應(yīng)的表結(jié)構(gòu): CREATE TABLE NWH.TT_20110710 (A INTEGER, B VARCHAR(20) ) ? ? 對應(yīng)生成的 SQL 類似: insert into nwh.tt_20110710(a,b) values (?,?) , (?,?) ? ? 注意: Map?map ,而物理表中一個 Ingeger 字段,一個 VARCHAR 字段, MyBatis 會自己做類型映射 ?
相關(guān)推薦: jdbc通用查詢通過map替代實體 ibatis dao的封裝討論(歡迎拍裝) 介紹DynamicQueryTool,一個用于解決“拼裝動態(tài)查詢”的小工具。 ibatis查詢返回java.util.HashMap結(jié)果列表 ibatis中動態(tài)查詢返回字段返回用resultClass="java.util.HashMap" 的問題 ibatis resultclass "java.util.hashmap" 緩存 ibatis中配置parameterClass="java.util.HashMap"的用法 ibatis中動態(tài)查詢表返回用resultClass="java.util.HashMap" 的問題 推薦群組: JSF 更多相關(guān)推薦 iBATIS 這兩天寫代碼時,遇到一個問題,要求在DAO層要返回一個java.util.HashMap的結(jié)果集,但是平常我們多返回List或者VO,在網(wǎng)上搜索了下,結(jié)果找到了這樣一個方法,記錄如下:DAO的實現(xiàn)類中的代碼: return Map getItemNames () { return getSqlMapClientTemplate().queryForMap("getItemNameMap", null, "key", "value"); } SqlMap配置文件中的代碼: select SKU, Description from Items 在業(yè)務(wù)層調(diào)用getItemNames()時,返回的結(jié)果已經(jīng)是一個標準的java.util.HashMap了,可以使用其方法 get(String key)來直接獲取對應(yīng)的value,非常方便。 參考地址: http://osdir.com/ml/java.ibatisdb.user/2005-01/msg00336.html
相關(guān)推薦: Ibator優(yōu)化版代碼生成過程 Ibator支持分頁的plugin ibator改造之返回數(shù)據(jù)庫注釋和數(shù)據(jù)庫分頁 ibatis自動生成工具ibator及配置文件示例 ibatis的ibatorForEclipse的安裝與配置和ibator的錯誤日志查看 ibatis:使用ibator自動生成代碼和配置文件 A code generator for iBATIS Myeclipse?8.5?下?iBATIS?的代碼生成插件?ibator安裝
推薦群組: struts2
更多相關(guān)推薦
iBATIS
源地址:
http://cache.baidu.com/c?m=9d78d513d99811fc1eb0d4690c66c0161e43f1652bd6a0020fd6843893732d445016e1ac26520774a0d20d1116ae394b9bf72105311456b38cb9895e9afbcc2775ce6176671df55c0f8942b8cb3175927bc61dfeaf6eb6e7af2f84d8d5c4ae5344bc56120c81e7fb501763c072a04a6cb6bbc20e42000db8ef3535fc587d289a7046e211f2ea303a0383f78e581fc83dd0164bd1f06b&p=8534d50c8c904eab1abd9b7f0e4f&user=baidu&fm=sc&query=ibator%B5%C4%B0%B2%D7%B0%BA%CD%C5%E4%D6%C3&qid=819f7ee217769ff1&p1=1
?
下載ibator插件地址:
http://people.apache.org/builds/ibatis/ibator/
http://people.apache.org/builds/ibatis/ibator/ibator-1.2.1-681.zip
http://people.apache.org/builds/ibatis/ibator/IbatorForEclipse1.2.1.zip
?
?
現(xiàn)在我們著手來寫一個ibatis的簡單例子.
如果你是使用eclipse開發(fā)項目的話,那么,有一個eclipse的插件ibator,可以通過 配置 自動生成java代碼sqlmap等,蠻好用。下面先做一個使用ibator插件的例子。
1.使用link方式在線 安裝 ibator。
eclipse菜單? help-->
software updates-->
add site-->(填入在線 安裝 地址:http://ibatis.apache.org/tools/ibator
-->一直下一步 安裝
2.新建一個web工程,導(dǎo)入相應(yīng)的包,我使用的數(shù)據(jù)庫是ORACLE,所以我需要導(dǎo)入的包是:
ojdbc14.jar或classes12.jar,把ibatis需要的jar包都導(dǎo)進去
此例我導(dǎo)入的jar包如下:
?
ojdbc14.jar
ibatis-common.jar
ibatis-dao.jar
ibatis-sqlmap.jar
?
3.由于你 安裝 了ibator插件,那么你在你的工程某個目錄下單擊右鍵-->new-->other里將會看到
Apache iBatis Ibator文件夾,下面只有一個選項
?
Apache iBatis ibator configuration File
?
點擊以后要求你輸入文件名(這個就是 ibator的 配置 文件):
?
Location: test/src
File name: ibatorConfig.xml
?
?
填入 配置 文件名稱,可以隨便設(shè)置 配置 文件名字。一般為“ibatorConfig.xml”,點確定后就創(chuàng)建好了一個ibator 配置 文件的模板。
代碼如下:
?
xml?version = " 1.0 " ?encoding = " UTF-8 " ? ?>
< ibatorConfiguration? >
< ibatorContext?id = " context1 " ? >
< jdbcConnection?driverClass = " ??? " ?connectionURL = " ??? " ?userId = " ??? " ?password = " ??? " ? />
< javaModelGenerator?targetPackage = " ??? " ?targetProject = " ??? " ? />
< sqlMapGenerator?targetPackage = " ??? " ?targetProject = " ??? " ? />
< daoGenerator?targetPackage = " ??? " ?targetProject = " ??? " ?type = " GENERIC-CI " ? />
< table?schema = " ??? " ?tableName = " ??? " ? >
< columnOverride?column = " ??? " ?property = " ??? " ? />
table >
ibatorContext >
ibatorConfiguration >
?
?
4.將對應(yīng) 配置 參數(shù)替換掉上面的“?”號。我自己的替換文件是這樣的:
?
?
?
5.之后我們只需要在這個 配置 文件上點擊右鍵-->點擊Generate ibatis artifacts,這樣就應(yīng)該能生成對應(yīng)的package 和 類了
?
?
6.如果出現(xiàn)錯誤使用一下方式查看錯誤日志
?
? 運行cmd用來查詢ibatorConfig.xml中出現(xiàn)的錯誤日志
java -jar d:\ibator.jar -configfile E:\Workspace\test\src\ibatorConfig.xml -overwrite >>c:\log.log
結(jié)貼,折騰了一天,剛發(fā)帖就找到原因了,我用了rapid-framework3.9.3,里面的分頁plugin可能有問題,再研究下。
相關(guān)推薦: mybatis和Spring的集成 整合Mybatis與Spring3 MyBatis3新手上路 Springboot整合MyBatis, yml配置,超詳細從mybatis-spring-boot-starter根據(jù)源碼進行配置,MybatisProperties類中的屬性【源碼版】) SpringBoot整合MyBatis-Plus3.1詳細教程 SpringBoot(十六):SpringBoot整合Mybatis-Plus spring boot集成mybatis-generator-maven-plugin和通用mapper MyBatis-Spring整合 推薦群組: 系統(tǒng)架構(gòu)與架構(gòu)應(yīng)用 更多相關(guān)推薦 iBATIS 從網(wǎng)上下載官方mybatis-spring整合示例源代碼,整合放上來,如果有必要的朋友可以下載,這里說的已經(jīng)很全了,最好是下載官方相關(guān)文檔來看。
相關(guān)推薦: ibatis源碼學(xué)習(xí)(三)參數(shù)和結(jié)果的映射原理 spring ibatis clob ibatis經(jīng)典示例 mule進階之ibatis component iBATIS入門知識進階四 iBatis高級應(yīng)用 ibatis學(xué)習(xí)進階 iBATIS SQL Maps之Result Map屬性進階。
推薦群組: JBPM @net
更多相關(guān)推薦
iBATIS
Ibatis比較少人使用的配置語法?
簡單來說,ibatis3雖然沒有ognl,不過也支持基本的表達式(看起來有點像el表達式的樣子) 上次有個問題,說到兩個表單數(shù)據(jù)(兩個javabean),入同一個表,傳參就應(yīng)該不成問題了
java代碼1:
Map map = new HashMap(); ComplexBean bean = new ComplexBean(); bean.setMap(new HashMap()); bean.getMap().put("id", new Integer(1)); map.put("bean", bean); Account account = new Account(); account.setId(2); Account anotherAccount = new Account(); anotherAccount.setId(3); map.put("accounts", new Account[] {account, anotherAccount}); Integer id = (Integer) sqlMap.queryForObject("mapBeanMap", map);
ibatis配置1:
select count(ACC_ID) from Account where ACC_ID in (#bean.map.id#,#accounts[0].id#,#accounts[1].id#) java代碼2:
Map map = new HashMap(); ComplexBean bean = new ComplexBean(); bean.setMap(new HashMap()); Account account = new Account(); account.setId(2); Account anotherAccount = new Account(); anotherAccount.setId(3); bean.getMap().put("accounts", new Account[] {account, anotherAccount}); map.put("bean", bean);
ibatis配置2:
select count(ACC_ID) from Account where ACC_ID in #bean.map.accounts[].id# 當使用復(fù)雜配置并且參數(shù)帶有泛型的時候,使用比較標簽有可能導(dǎo)致如下錯誤: There is no READABLE property named ‘XXX’ in class ‘java.lang.Object’ .這是因為進行比較的時候,ibatis是通過反射獲取類型而不是先計算值的,這樣泛型的時候會獲取到Object類而不能得到真實的類型,自己簡單打個補丁先:
Index: src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/elements/ConditionalTagHandler.java =================================================================== --- src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/elements/ConditionalTagHandler.java (revision 1079874) +++ src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/elements/ConditionalTagHandler.java (working copy) @@ -72,14 +72,13 @@ if (prop != null) { value1 = PROBE.getObject(parameterObject, prop); - type = PROBE.getPropertyTypeForGetter(parameterObject, prop); } else { value1 = parameterObject; - if (value1 != null) { - type = parameterObject.getClass(); - } else { - type = Object.class; - } + } + if (value1 != null) { + type = value1.getClass(); + } else { + type = Object.class; } if (comparePropertyName != null) { Object value2 = PROBE.getObject(parameterObject, comparePropertyName); ?
關(guān)于inlineParameterMap
例如#name#(標準配置),#name:NUMBER#(以:分割),#myVar:javaType=int#都是有效的
其中以:分割的有兩種方式,#name:jdbcTypeName#,#name:jdbcTypeName:nullvalue#(如果后面還有則會被加到nullvalue上去) 這是老配置方法,個人不推薦使用。
最后一種是新的配置方式,可以帶上javaType,jdbcType,mode,nullValue,numericScale,handler等參數(shù)(這個文檔有詳細描述)
jdbcType,javaType和TypeHandler
首先要說明一點的是,配置里邊的jdbcType和javaType兩個配置參數(shù)是為了生成TypeHandler(如果沒有指定的話);
查找typeHandler的內(nèi)部結(jié)構(gòu)是Map
>,其中javaType是一個類,jdbcType是一個字符串; 所以jdbcType其實和數(shù)據(jù)庫的字段類型沒什么關(guān)系,只要能找到相應(yīng)的TypeHandler即可(當然通常都會對應(yīng)上); typeHandler主要是做什么用的呢?無非就是使用jdbc api的時候選擇setString/setInt還是getString/getObject之類~~ 只指定resultClass,沒有resultMap 如果沒有指定resultMap,ibatis會根據(jù)parameterClass生成一個AutoResultMap對象; 對于AutoResultMap,里邊的每個屬性的映射對應(yīng)的typeHandler是什么? resultClass TypeHandler Map ObjectTypeHandler 原型類型 Bean 相應(yīng)類對應(yīng)的typeHandler(javaType=?,jdbcType=null) 會對實例變量名稱進行大寫并和ResultSetMetaData信息進行對比,最后生成typeHandler(javaType=?,jdbcType=null)
所以使用parameterClass是map的時候,某些字段的處理可能會有點問題,例如oracle的NUMBER類型會被轉(zhuǎn)成BigDecimal類; 只指定parameterClass,沒有parameterMap 如果沒有指定parameterMap,就會根據(jù)配置的sql解析inlineParameterMap; 其中每個參數(shù)的TypeHandler如果沒有指定,會根據(jù)參數(shù)的類型來尋找,例如#name,jdbcType=NUMBER# 會根據(jù)name計算后的類型來制定javaType 這個typeHandler的好處可以對jdbc api友好,例如對于int默認會采用IntegerTypeHandler,這樣會調(diào)用PreparedStatement#setInt, 而不是統(tǒng)統(tǒng)setString或者setObject。 通常參數(shù)類型和jdbc類型不對應(yīng)的時候,需要考慮設(shè)置typeHandler或者使用更強類型的Bean而不是統(tǒng)統(tǒng)使用map; sqlmap文件"合并"以前還真沒用過,感覺這樣對于同一個業(yè)務(wù)的多個應(yīng)用采用統(tǒng)一的core包還有有些用處的,不錯,謝謝分享!
相關(guān)推薦: 一個iBatis的demo iBatis2 實現(xiàn) 增 刪 改 查 iabtis 測試通過的例子 ibatis2.3.4 + h2 1.3.146數(shù)據(jù)不能保存的問題 Spring3.0.x API在線參考教程—https://docs.spring.io/spring/docs/ Java工程師成神之路 推薦群組: DI 更多相關(guān)推薦 iBATIS 一個簡單的測試用例中ibatis2.3.4 + h2 1.3.146。只有一個map類, H2是用的Embedded模式運行的 ? package org.jamsa case class User(var userName:String,var id:Int){ def this()=this("abc",-1) } import com.ibatis.sqlmap.client.SqlMapClientBuilder import com.ibatis.common.resources.Resources object Client { val sqlMapClient = initSqlMapClient(); private def initSqlMapClient()={ SqlMapClientBuilder.buildSqlMapClient(Resources.getResourceAsReader("sql-map-config.xml")) } } import com.ibatis.common.resources.Resources import Client.sqlMapClient object UserDao { def getUser(id:Int)={ sqlMapClient.queryForObject("getUser",id).asInstanceOf[User] } def addUser(user:User)={ sqlMapClient.insert("addUser",user) } def deleteUser(id:Int)={ sqlMapClient.delete("deleteUser",id) } def main(args:Array[String]){ var user = User("abc5",5) addUser(user) Thread.sleep(2000) } } ??如果不加Thread.sleep這行,數(shù)據(jù)就不會被保存到數(shù)據(jù)庫里去。 從控制臺可以看到語句都執(zhí)行了,但是數(shù)據(jù)沒有被保存進去。 如果H2以Server模式運行,沒有出現(xiàn)這個問題。 暫時沒找到具體原因
超級潛水艇 寫道 注解與xml配置之間有性能上的差異嗎? 如果全用annotation感覺要靈活一些 注解適用小型項目,缺點主要是對于同一切入點需要復(fù)制,黏貼相同的一段@Transaction,反而來的繁瑣。
相關(guān)推薦: iBatis分頁 iBatis batch處理那些事 ibatis源碼學(xué)習(xí)(一)整體設(shè)計和核心流程 從iBatis中得到PreparedStatement 項目開發(fā)-iBatis事務(wù)源碼之SQL執(zhí)行 ibatis 學(xué)習(xí)筆記 3 ibatis 中blob的使用 [ibatis]動態(tài)映射 推薦群組: IBM WebSphere專區(qū) 更多相關(guān)推薦 iBATIS iBatis是個好東西,特別是他的動態(tài)SQL構(gòu)建,其實也是選它的原因,除去這個熱點,spring的jdbcTemplate更加的 smart。但并不是封裝的越完整越好,有時候我們需要用到preparentStatement和resultset,進行一些例外的操作,這時還要用到動態(tài)生成的sql和參數(shù)的封裝,只能從iBatis處想辦法了。從現(xiàn)有的iBatis中無法得到這些對象,拿源代碼來跟蹤一下,改改(開源的好處之一:源代碼)?! ∽⒁猓涸摳淖儍H對查詢,如果對于更新或其它的,還是調(diào)用iBatis的缺省function較好,保證事務(wù)的完整和緩存的更新。 水平有限,有什么不對的地方,請大家包涵并指正! 1.對SqlMapClient增加幾個接口 /** * 不執(zhí)行具體的查詢,返回一個SessionScope,利用這個sessionScope,返回一個statement * 記得用closeSessionScope來關(guān)閉 * @return */ public SessionScope getSessionScope(); /** * 根據(jù)傳入的sessionScope,關(guān)閉 * @param scope */ public void closeSessionScope(SessionScope scope); /** * 你要調(diào)用 sessionScope.getSqlMapTxMgr().endTransaction() * sessionScope.cleanup(); * sessionScope.closePreparedStatements() * 釋放相關(guān)資源 * 或sqlMapClient.closeSessionScope() * * @param session * @param sqlId * @param paramObject * @return * @throws SQLException */ public PreparedStatement makePreparedStatement(SessionScope session,String sqlId,Object paramObject) throws SQLException; 2.SqlMapClientImpl實現(xiàn)上面的接口 /** * 不執(zhí)行具體的查詢,返回一個SessionScope,利用這個sessionScope,調(diào)用sqlMapClient.makePreparedStatement返回一個statement * 你要調(diào)用 sessionScope.getSqlMapTxMgr().endTransaction() * sessionScope.cleanup(); * sessionScope.closePreparedStatements() * 釋放相關(guān)資源 * @return */ public SessionScope getSessionScope(){ return this.getLocalSqlMapSession().sessionScope; } /** * 根據(jù)傳入的sessionScope,關(guān)閉 * @param scope */ public void closeSessionScope(SessionScope scope){ try{ scope.getSqlMapTxMgr().endTransaction(); } catch(Exception e){} scope.closePreparedStatements(); scope.cleanup(); } /** * 利用sessionScope生成一個preparedStatement * by wangqiang 2010.01.12 */ public PreparedStatement makePreparedStatement(SessionScope session,String sqlId,Object paramObject) throws SQLException{ return this.delegate.makePreparedStatement(session, sqlId, paramObject,this); } 3.SqlMapExecutorDelegate 增加 public PreparedStatement makePreparedStatement(SessionScope sessionScope, String id, Object paramObject,SqlMapClientImpl sqlMapClient) throws SQLException{ PreparedStatement ps = null; Transaction trans = getTransaction(sessionScope); boolean autoStart = trans == null; try { trans = autoStartTransaction(sessionScope, autoStart, trans); MappedStatement ms = getMappedStatement(id); ms.setSqlMapClient(sqlMapClient); StatementScope statementScope = beginStatementScope(sessionScope, ms); sessionScope.getCurrentConnection="+sessionScope.getSqlMapClient().getCurrentConnection()); ps = ms.makePreparedStatement(statementScope, Unwind.unwindConnection(sessionScope.getSqlMapClient().getCurrentConnection()), paramObject); endStatementScope(statementScope); }catch(Exception e){ e.printStackTrace(); throw new SQLException(e); } return ps; } 4.MappedStatement 增加 public PreparedStatement makePreparedStatement(StatementScope statementScope, Connection conn, Object parameterObject) throws SQLException{ parameterObject = validateParameter(parameterObject); Sql sql = getSql(); ParameterMap parameterMap = sql.getParameterMap(statementScope, parameterObject); statementScope.setParameterMap(parameterMap); Object[] parameters = parameterMap.getParameterObjectValues(statementScope, parameterObject); String sqlString = sql.getSql(statementScope, parameterObject); return getSqlExecutor().makePreparedStatement(statementScope, conn, sqlString, parameters); } 5.SqlExecutor 增加 ////////////////////// /** * by wangqiang 2010.01.12 */ public PreparedStatement makePreparedStatement(StatementScope statementScope, Connection conn, String sql, Object[] parameters) throws SQLException{ PreparedStatement ps = null; try{ Integer rsType = statementScope.getStatement().getResultSetType(); if (rsType != null) { ps = prepareStatement(statementScope.getSession(), conn, sql, rsType); } else { ps = prepareStatement(statementScope.getSession(), conn, sql); } setStatementTimeout(statementScope.getStatement(), ps); Integer fetchSize = statementScope.getStatement().getFetchSize(); if (fetchSize != null) { ps.setFetchSize(fetchSize.intValue()); } statementScope.getParameterMap().setParameters(statementScope, ps, parameters); } catch(Exception e){ throw new SQLException(e); } return ps; } 6.新建一個java,因為iBatis的connection,statement,resultset都通過proxy來生成的,需要得原始的這些對象 Unwind.java public class Unwind { public static Connection unwindConnection(Connection connection) { if (connection == null) { return null; } Connection localConnection = connection; while (Proxy.isProxyClass(localConnection.getClass())) { InvocationHandler ih = Proxy.getInvocationHandler(localConnection); if (ih instanceof ConnectionLogProxy) { localConnection = ((ConnectionLogProxy) ih).getConnection(); } else if (ih instanceof SimplePooledConnection) { localConnection = ((SimplePooledConnection) ih).getRealConnection(); } else { // some other non iBATIS proxy - jump out break; } } return localConnection; } public static PreparedStatement unwindPreparedStatement(PreparedStatement statement) { if (statement == null) { return null; } PreparedStatement localStatement = statement; while (Proxy.isProxyClass(localStatement.getClass())) { InvocationHandler ih = Proxy.getInvocationHandler(localStatement); if (ih instanceof PreparedStatementLogProxy) { localStatement = ((PreparedStatementLogProxy) ih).getPreparedStatement(); } else { // some other non iBATIS proxy - jump out break; } } return localStatement; } public static Statement unwindStatement(Statement statement) { if (statement == null) { return null; } Statement localStatement = statement; while (Proxy.isProxyClass(localStatement.getClass())) { InvocationHandler ih = Proxy.getInvocationHandler(localStatement); if (ih instanceof StatementLogProxy) { localStatement = ((StatementLogProxy) ih).getStatement(); } else { // some other non iBATIS proxy - jump out break; } } return localStatement; } public static ResultSet unwindResultSet(ResultSet resultset) { if (resultset == null) { return null; } ResultSet localResultset = resultset; while (Proxy.isProxyClass(localResultset.getClass())) { InvocationHandler ih = Proxy.getInvocationHandler(localResultset); if (ih instanceof ResultSetLogProxy) { localResultset = ((ResultSetLogProxy) ih).getRs(); } else { // some other non iBATIS proxy - jump out break; } } return localResultset; } } 還有,對有些不是public 的function,改成public就行了。 寫段代碼測試一下: ApplicationContext context = null; String path="D:/myproject/java/myQTEIS_lib/spring"; String[] spfiles= new String[4]; spfiles[0] = path+"/spring.xml "; spfiles[1] = path+"/spring_ibatis.xml "; spfiles[2] = path+"/spring_logistics.xml "; spfiles[3] = path+"/spring_logistics_service.xml "; context = new FileSystemXmlApplicationContext(spfiles); DaoBase dao = (MaterialCatalogDaoImpl)context.getBean("materialCatalogDao"); Map pms = new HashMap(); PreparedStatement stm = null; ResultSet rs = null; int ii = 35; pms.put("fldid", ii); try { SessionScope ses = dao.getSqlMapClient().getSessionScope(); dao.wrapLimited(pms, -1, 1000); stm = dao.getSqlMapClient().makePreparedStatement(ses, ((DaoBase)dao).getSelectSQLName(), pms); stm.execute(); System.out.println("ses:"+ses.toString()); System.out.println("iBatisMain statement(37)="+stm.getMetaData().getColumnCount()); stm.close(); ses.getSqlMapTxMgr().endTransaction(); ses.cleanup(); ses.closePreparedStatements(); System.out.println("ses:"+ses.toString()); } catch (SQLException e) { e.printStackTrace(); } finally{ try { stm.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } stm=null; } OK,得到了想要的!
相關(guān)推薦: Spring集成iBATIS ibatis事務(wù)管理問題--無法實現(xiàn)事務(wù)回滾 解決Spring導(dǎo)致iBatis緩存失效問題 Ibatis之緩存插件 強制刷新Ibatis中的緩存(OSCache) ibatis緩存的設(shè)置使用 引用iBatis中oscache實現(xiàn)自定義緩存及動態(tài)更新技巧 iBATIS 配置oscache緩存 錯誤(未解決) 推薦群組: DI 更多相關(guān)推薦 iBATIS 持久層使用Ibatis,并開啟動緩存后臺畫面可用如下代碼強制刷新(根據(jù)緩存ID來刷新,不傳遞緩存參數(shù)時,刷新所有緩存) // spring注入 private SqlMapClient sqlMapClient; public SqlMapClient getSqlMapClient() { return sqlMapClient; } public void setSqlMapClient(SqlMapClient sqlMapClient) { this.sqlMapClient = sqlMapClient; } public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String[] cacheModelIds = new String[] { "TBL_SELL.oneDayCache" }; // 刷新指定緩存 if (cacheModelIds.length > 0) { for (String cacheModelId : cacheModelIds) { sqlMapClient.flushDataCache(cacheModelId); } } else { // 刷新所有緩存 sqlMapClient.flushDataCache(); } return null; } 輸出日志 13:57:44,250 DEBUG CacheModel:27 - Cache 'TBL_SELL.oneDayCache': flushed
sw1982 寫道 比2爽在哪里?我只用過2 比如說動態(tài)語言支持,ognl表達式,表關(guān)系一對多處理,不過對2研究不深。 從學(xué)習(xí)成本來說,3應(yīng)該簡單些。但現(xiàn)在穩(wěn)定性應(yīng)該是2
對于數(shù)據(jù)庫切分,麻煩之一就是分頁查詢等查詢。。沒用過guzz ,不知道是否已經(jīng)解決了。。大概看了下文檔,沒怎么說明。。稍微網(wǎng)上知道的比較好的數(shù)據(jù)庫切分的中間件是阿里巴巴的amoeba
如果第一種能夠滿足你的要求,就用第一種;如果不行,就得用回調(diào)方法自己寫
你的這種事務(wù)應(yīng)用的方法是錯誤的1、你把事務(wù)管理放到了dao層是個錯誤,dao層不涉及事務(wù)方面的東東,你現(xiàn)在的做法的結(jié)果是Spring管理的是你的personDAO的事務(wù),在你的測試用例里Spring是對personDAO的save方法進行事務(wù)管理,你添加一個person,如果不拋出runtimeexception,事務(wù)就會提交,你調(diào)用兩次save方法就是兩次事務(wù),兩者是分開的,當然不會回滾 2、事務(wù)管理應(yīng)該放在服務(wù)層或業(yè)務(wù)層,比如說在服務(wù)層有個save方法,這個方法里面可以調(diào)用多個dao操作,事務(wù)管理應(yīng)該加在服務(wù)層對象上。 3、另外要注意的是:你在調(diào)用服務(wù)層方法時,注入的參數(shù)bean應(yīng)該是動態(tài)代理bean
IOC的核心是對于依賴性管理的思想,最好的一句話還是好萊塢原則(當然如果用“依賴注入”更容易理解),反射、動態(tài)代理只是實現(xiàn)的工具。
求人不如求己,暴力方法解決,你不是要resource嗎?我給你個FileSystemResource.什么?沒setPath()?繼續(xù)暴力,給構(gòu)造參數(shù)........
conf/jdbc.properties 相關(guān)推薦: [原創(chuàng)] 如何在Android Market賺錢 part 2 - 免費app附帶廣告 談?wù)刟ndroid下免費+廣告的盈利模式 admob廣告看來也能賺錢 ios下應(yīng)用程序檢測admob廣告請求返回和點擊事件 admob Google AdMob Ads iOS Fundamentals ios如何介入蘋果廣告_蘋果公司的iOS 14廣告股票面臨新的重大挑戰(zhàn) 某Java大佬在地表最強Java企業(yè)(阿里)面試總結(jié) 推薦群組: Android 更多相關(guān)推薦 iOS AdMob目前為止提供了最方便的iPhone app廣告集成庫.廣告的形式是一段320x48的長條橫跨屏幕, 點擊會scroll出來一個廣告網(wǎng)頁, 這算一個點擊. 首先先去AdMob.com注冊帳號, 然后建立你的項目, 每個項目會獲得一個ID, 集成AdMob庫的時候指定這個ID就可以了. 然后下載AdMob iPhone SDK, 里面包括了所有一切相關(guān)的庫, 文檔和樣本. 他們的SDK用到了CoreLocation, CoreGraphics和QuartzCore框架. 集成的方式有三種: 1) 在Interface Builder中放一個320x48的UIView, 加入一個Object, 類型選AdViewController, 然后指定這個controller的view outlet為這個UIView, 就完成了. 2) 在你的程序里, 建立一個AdMob的delegate代理類, 里面只需實現(xiàn) -publisherId:的方法. 在你建立view的時候, 加入如下代碼: AdMobView *ad = [AdMobView requestAdWithDelegate:你的delegate instance]; ad.frame = CGRectMake(0, 432, 320, 48); // 屏幕底部一個320x48的框架 [self.window addSubview:ad]; // 把這個view加入到window的subviews里面 3) 在tableview中加一行Ad廣告 同樣, 先建立一個delegate. 在"-tableView:cellForRowAtIndexPath:"方法中: [cell.contentView addSubview:[AdMobView requestAdWithDelegate:你的delegate實例]]; *AdMob使用了TouchJSON的庫(以后再講這個庫) 你當然還要把AdMob的庫文件加入你的項目中, 一個4個文件: AdMobDelegateProtocol.h, AdMobView.h, libAdMobDevice.a, libAdMobSimulator.a ^_^ 人品好的就準備開始數(shù)錢吧~~~ 目前看來iPhone的banner收入比Android要好, 大概是廣告商更喜歡iPhone平臺的緣故. *附件是我前幾天下雪堆的一個小雪人... -___-#
相關(guān)推薦: 大家這么熱情,我就獻丑了 -- 我的iPhone軟件 日本生活旅游必備 日本電車導(dǎo)航地圖 - 日本の駅M 很牛的彈出層看看不后悔 ios 上傳APP到APP STORE注意事項 當 App Store 遇上電視,開發(fā)者的第四代 Apple TV 開箱體驗 為Apple ID更換地區(qū),下載非國內(nèi)APP 六大生態(tài)系統(tǒng)的崛起:Apple、Google、Microsoft、Facebook、Amazon、Sony iOS 資源大全 推薦群組: 電腦DIY 更多相關(guān)推薦 iOS 刷新歷史記錄 ,下圖第十名是Fifa 10日本top grossing 上 周圍都是CAPCOM,TAITO ,Gameloft,Namco等著名公司,有些做夢的感覺。
相關(guān)推薦: Mac OS中的mysql驅(qū)動 IPHONE 新手入門之前 關(guān)于在IOS環(huán)境下進行視頻通訊開發(fā) iOS 開發(fā) Xcode 8.1創(chuàng)建新項目的配置--詳解 XCode編譯器里有鬼 – XCodeGhost樣本分析 XCode版本介紹和演變史 XCode 下的 iOS 單元測試 不可能不愛的 XCODE 9:最新功能詳盡介紹 推薦群組: 高級語言虛擬機 更多相關(guān)推薦 iOS 最近升級到Snow Leopard,然后升級XCode到3.2。不是我想升級,是因為我升級完Snow Leopard之后,雖然XCode可以編譯iPhone的程序,不過我沒辦法在我的MacBook上學(xué)習(xí)Unix編程了,因為/usr/include里面都刪空了。升級完之后我才后悔了,因為XCode3.2在SnowLeopard上沒有iPhone2.2的模擬器,不過可以為2.2生成程序。 所以如果大家有Legacy的代碼要維護,請不要做這樣的升級。 當然從這點,大家也可以看到蘋果在鼓勵大家放棄2.x。不過升級之后的好處也是很多的,我列舉幾個我體會到的。 ? [1] 文檔系統(tǒng)。我自己是覺得新的文檔系統(tǒng)更好用,不過每次按住Option鍵,然后雙擊,都會彈出一個框,問你選擇文檔還是頭文件。這個我覺得是可以關(guān)掉的,不過現(xiàn)在還沒有找到。 [2] 以前如果你寫 MyObject *a = [MyObject alloc]init],然后你發(fā)現(xiàn)漏寫了一個[,你就要回到前面去補?,F(xiàn)在 不用了,XCode會自動幫你完成,不信你可以試一下。 ? [3] 修改公司名字。以前需要用這個命令才可以做到: defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{"ORGANIZATIONNAME" = "ABC";}' 現(xiàn)在有個簡單的方法。Ctrl+點擊項目,然后選擇Get Info,然后在General選項頁下面你可以填入你公司的名字: 不過在你做這個修改這前項目里文件的公司名字不會被更改,之后的都會用這個新的。這個功能非常適用。 如果大家發(fā)現(xiàn)了什么新的,可以回復(fù)我這個帖子。這樣大家的經(jīng)驗就可以被累計了。 對了,這里有個不錯的帖子:? http://stackoverflow.com/questions/146297/what-are-those-little-xcode-tips-tricks-you-wish-you-knew-about-2-years-ago
相關(guān)推薦: 求求你們,千萬別再說自己是REST了 weblogic8.1 虛擬主機配置問題 How Microsoft Lost the API War Xcode 自動屬性生成器(強力推薦) xcode ios gdb iOS開發(fā)系列——內(nèi)購、GameCenter、iCloud、Passbook系統(tǒng)服務(wù)開發(fā)匯總 HTML5最終會成為iOS和Android替代者嗎? 使用 Assets Processor 處理 Xcode @3x @2x圖片資源 推薦群組: D語言 更多相關(guān)推薦 iOS 一次偶然機會從git上找到,可惜沒有添加關(guān)注。現(xiàn)在忘記從哪里clone 出來了。 應(yīng)該是目前最好用的自動補上屬性? ? @property()xx??? @syn delloc 功能。 ? ? 代碼 寫道 #! /usr/bin/perl -w # Created by Matt Gallagher on 20/10/08. # Copyright 2008 Matt Gallagher. All rights reserved. # # Permission is given to use this source code file without charge in any # project, commercial or otherwise, entirely at your risk, with the condition # that any redistribution (in part or whole) of source code must retain # this copyright and permission notice. Attribution in compiled projects is # appreciated but not required. use strict; # Get the header file contents from Xcode user scripts my $headerFileContents = <<'HEADERFILECONTENTS'; %%%{PBXAllText}%%% HEADERFILECONTENTS # Get the indices of the selection from Xcode user scripts my $selectionStartIndex = %%%{PBXSelectionStart}%%%; my $selectionEndIndex = %%%{PBXSelectionEnd}%%%; # Get path of the header file my $implementationFilePath = "%%%{PBXFilePath}%%%"; my $headerFilePath = $implementationFilePath; # Look for an implemenation file with a ".m" or ".mm" extension $implementationFilePath =~ s/\.[hm]*$/.m/; if (!(-e $implementationFilePath)) { $implementationFilePath =~ s/.m$/.mm/; } # Handle subroutine to trime whitespace off both ends of a string sub trim { my $string = shift; $string =~ s/^\s*(.*?)\s*$/$1/; return $string; } # Get the selection out of the header file my $selectedText = substr $headerFileContents, $selectionStartIndex, ($selectionEndIndex - $selectionStartIndex); $selectedText = trim $selectedText; my $selectedLine; foreach $selectedLine (split(/\n+/, $selectedText)) { my $type = ""; my $asterisk = ""; my $name = ""; my $ivarName = ""; my $behavior = ""; my $isPointer = 0; # Test that the selection is: # At series of identifiers (the type name and access specifiers) # Possibly an asterisk # Another identifier (the variable name) # A semi-colon if (length($selectedLine) && ($selectedLine =~ /([_A-Za-z][_A-Za-z0-9]*\s*)+([\s\*]+)([_A-Za-z][_A-Za-z0-9]*);/)) { $type = $1; $type = trim $type; $asterisk = $2; $asterisk = trim $asterisk; $ivarName = $3; if ($ivarName =~ /^_(.*)/) { $name = $1; } else { $name = $ivarName; } $behavior = ""; if (defined($asterisk) && length($asterisk) == 1) { $isPointer = 1; if ($type eq "NSArray" || $type eq "NSString" || $type eq "NSDictionary" || $type eq "NSSet") { $behavior = "(nonatomic, copy) "; } else { $behavior = "(nonatomic, retain) "; } } else { $isPointer = 0; $behavior = "(nonatomic, assign) "; $asterisk = ""; } } else { next; } # Find the closing brace (end of the class variables section) my $remainderOfHeader = substr $headerFileContents, $selectionEndIndex; my $indexAfterClosingBrace = $selectionEndIndex + index($remainderOfHeader, "\n}\n") + 3; if ($indexAfterClosingBrace == -1) { exit 1; } # Determine if we need to add a newline in front of the property declaration my $leadingNewline = "\n"; if (substr($headerFileContents, $indexAfterClosingBrace, 1) eq "\n") { $indexAfterClosingBrace += 1; $leadingNewline = ""; } # Determine if we need to add a newline after the property declaration my $trailingNewline = "\n"; if (substr($headerFileContents, $indexAfterClosingBrace, 9) eq "\@property") { $trailingNewline = ""; } # Create and insert the propert declaration my $propertyDeclaration = $leadingNewline . "\@property " . $behavior . $type . " " . $asterisk . $name . ";\n" . $trailingNewline; substr($headerFileContents, $indexAfterClosingBrace, 0) = $propertyDeclaration; my $replaceFileContentsScript = <<'REPLACEFILESCRIPT'; on run argv set fileAlias to POSIX file (item 1 of argv) set newDocText to (item 2 of argv) tell application "Xcode" set doc to open fileAlias set text of doc to newDocText end tell end run REPLACEFILESCRIPT # Use Applescript to replace the contents of the header file # (I could have used the "Output" of the Xcode user script instead) system 'osascript', '-e', $replaceFileContentsScript, $headerFilePath, $headerFileContents; # Stop now if the implementation file can't be found if (!(-e $implementationFilePath)) { exit 1; } my $getFileContentsScript = <<'GETFILESCRIPT'; on run argv set fileAlias to POSIX file (item 1 of argv) tell application "Xcode" set doc to open fileAlias set docText to text of doc end tell return docText end run GETFILESCRIPT # Get the contents of the implmentation file open(SCRIPTFILE, '-|') || exec 'osascript', '-e', $getFileContentsScript, $implementationFilePath; my $implementationFileContents = do {local $/;