这iBATIS的老大爱折腾,搬来搬去,看陈述的那些理由,我唯一的感觉就是:他厌倦了ASF的官僚作风。 对用户影响很小,开源协议也没变,还是最宽松的Apache 2.0,Google的网络也比Apache快点。 不过MyBatis这个名字可不如iBATIS,让人还以为是iBATIS的定制项目,比如MyEclipse和Eclipse。
相关推荐: ibator改造之返回数据库注释和数据库分页 ibatis的ibatorForEclipse的安装与配置和ibator的错误日志查看 Ibator优化版代码生成过程 Ibator支持分页的plugin mybatis (Ibatis ibator) generator - 1 mysql 分页插件(page/paging/pagination plugin) 基于Struts2+Spring+iBatis的web应用最佳实践系列之五(分页篇) ibator改造之返回数据库注释和数据库分页 推荐群组: struts2 更多相关推荐 iBATIS 首先声明:该文章 参照了 http://www.iteye.com/topic/674839 matychen 的文章 , 修改了一下 ibator 的工作方式,实际分页的原理还是一样的 , 支持 oracle,mysql , 如果涉及侵犯matychen的利益,请告知,我立即删除 /** * * @author coffeesweet * */ Ibator 支持分页的 plugin 式的开发步骤 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 以上所有修改的类搜索 “ 增加开始 ” 或者 “ 增加结束 ” 就能找到修改的地方 2: 示例 ibatorConfig.xml 文件 一定要注意该 xml 的元素顺序 子元素的 第一个 位置 ibatorContext 的子元素顺序是 (property*, ibatorPlugin*, commentGenerator?, jdbcConnection, javaTypeResolver?, javaModelGenerator, sqlMapGenerator, daoGenerator?, table+) 所以需要注意 ibatorPlugin 的位置,还有,如果有多个 plugin 的话,加入第一个的 validate 失败,那么余下的所有 plugin 都不执行了 还要注意 ibatorPlugin 的两个必要属性 < property name = "enablePagination" value = "true" /> < property name = "dbType" value = "oracle" /> 示例 ibatorConfig.xml xml version = "1.0" encoding = "UTF-8" ?> < ibatorConfiguration > < classPathEntry location = "oracle驱动的本地绝对路径" /> < 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 源码里的有关数据连接信息的东西请自行修改 测试用到了spring ibator.jar可直接拿到工程中使用
相关推荐: 数据库水平切分的实现原理解析 关于ibatis进行物理游标分页 数据库分切设计何必纠结于hibernate shard模式,应该简单化了 [] 通过ibatis实现轻量级的水平切分(已更新,ibatis原生api也可以实现sharding) 通过ibatis实现轻量级的水平切分(已更新,ibatis原生api也可以实现sharding) Ibatis实现分表 数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示 数据库水平切分的原理探讨、设计思路--数据库分库,分表,集群,负载均衡器... 推荐群组: lucene爱好者 更多相关推荐 iBATIS 最近想在自己的项目里实现DB sharding功能,正好前段时间研究过ibatis的源码于是就在ibatis的基础上进行了一些修改。另一方面也是为了练练手。这个sharding的实现主要是基于我项目中的需求实现的可能有很多考虑不周的地方,希望各位大牛拍砖。如果有人感兴趣愿意一起来发展这个项目,本人也非常欢迎各位的加入。Shardbatis是在mybatis 2.3.5代码的基础上进行一些扩展实现数据水平切分功能。 数据的水平切分包括多数据库的切分和多表的数据切分。目前shardbatis已经实现了单数据库的数据多表水平切分 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的实现是的ibatis具有了DB sharding的功能,iBATIS会自动根据配置的或者是编码的sharding策略将原始的sql语句转变为对应目标表名的sql。 下面看一下如何在iBATIS中配置和使用sharding功能 1.配置sharding策略。在sql-map-config.xml中添加如下配置 这里再通过实例简单介绍一下使用DefaultShardingStrategy时对sql的convert结果 比如sqlmap中定义的原始sql为: SELECT EMPLOYEEIDNO FROM mytable WHERE SALARY >= 50000 那经过convert后的结果将可能是 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的结果可能为 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为切分策略提供必要参数 g.setTableName("App_Test");//设置为哪张表配置切分策略 g.setParam(new Integer(123));//设置为切分策略提供参数 //这里还可以通过g.setShardingStrategy(...)来设置切分策略 //通过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"); } } 实现自己的sharding策略,只要实现一个简单的接口即可 public interface ShardingStrategy { /** * 计算得到新的表名 * @param baseTableName 逻辑表名 * @param params 为sharding逻辑提供必要参数 * @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没有区别 最终执行的SQL可能是如下样式 select count(*) from app_test_0 where cnt=? 关于shardbatis在spring中的使用方法,以及一些使用注意事项和性能测试结果请大家移步到项目主页 http://code.google.com/p/shardbatis/ 上查看
相关推荐: 大家觉得现在搞iPhone的软件开发有前途(钱途)吗? 手机safari的AJAX开发(包括iPhone) 盘点免费文件网络同步、备份工具 ios 开源的电子书阅读器项目 直接拿来用!最火的iOS开源项目 OpenDigg iOS开源项目月报201704 iOS开源系列——完整开源项目 推荐群组: iphone,ipod touch开发 更多相关推荐 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,但是看这个功能应该可以用在一个view上加custom的button实现的
IBatis 要强于hiberante1.项目一般数据库明确,不需要支持多数据库,用hibernate 也不表示能完全兼容所有数据库的所有select 语法(函数) 2.IBatis 的2员表达式 优于使用 hibernate QBC 3.开发速度取决于开发人员的水平 而不于ibatis 和 hibernate(虽然可以生成.java .hbm.xml) 4.
agapple 写道 LZ还可以考虑另一种思路,需要客户端指定Entry的主键Key,每次update操作,清空有包含该key的相关cache数据即可。 目前似乎是在服务端拦截select 类型的query 或取参数来得到key,不知道你说的客户端如何指定entry的主键key.
相关推荐: 使用Atomikos Transactions Essentials实现多数据源JTA分布式事务 Spring中事物管理一二 Spring配置一个事务中多个数据源 spring mybatis atomikos分布式事务 【分布式】springboot + mybatis + JTA + Atomikos 实现多数据源的分布式事务管理 spring+mybatis+atomikos 实现JTA事务 springboot实现mybatis分布式事务(atomikos) spring boot+Mybatis+mysql+atomikos+jta实现多数据源分布式事务
推荐群组: struts2
更多相关推荐
iBATIS
最近弄一个框架,使用spring3.0.5+mybatis3.0.5,需要访问多库,要应用分布式事务JTA,这是用atomikos 3.70版本,并把配置做一下记录。
配置多个数据源
SELECT 1 SELECT 1 配置mybatis的SessionFactory
这里使用的是SessionFactory,不是 org.springframework.orm.ibatis.SqlMapClientFactoryBean,在mybatis3中用 SqlMapClientFactoryBean汇报 com.ibatis.common.xml.NodeletException 异常。
configLocation 对应的mybatis配置,跟平时配置一样。
事务这块用spring管理atomikos
true Mapper的管理及注入
atomikos的配置jta.properties,该文件放在应用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中,调用事务的方法不能try。。。catch事务的方法,否者不能回滚
如下带面就会出现不会滚问题
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接口,稍后补充上吧。 望大家来拍拍转吧
Mybatis已经全面支持了!类似struts2对OGNL的操作. 楼主可以尝试下.可以写类似 ...... foreach很有用,在解决集合到sql转换的问题上很给力! 比如 in()
相关推荐: Extjs3综合应用(待续v4...初版) Mybatis3.0查询,保存,更新,删除数据。 summercool-ddl框架简介 (二) MyBaits中Insert至动态表名及foreach使用 在ibatis中使用oracle insert all 函数 MyBatis动态sql_foreach下foreach批量插入两种方式 mybatis中foreach的用法(转) 推荐群组: struts2 更多相关推荐 iBATIS 下面是一个简单的使用动态表名和 foreach 使用的简单配置 insert into nwh.tt_${suffix}(a,b) values (#{obj[order]},#{obj[name]}) ${suffix} "${}" 只做简单的替换 #{ obj [order]}"#{}"会做处理 对应的数据结构如下面代码表示: 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); 对应的表结构: CREATE TABLE NWH.TT_20110710 (A INTEGER, B VARCHAR(20) ) 对应生成的 SQL 类似: insert into nwh.tt_20110710(a,b) values (?,?) , (?,?) 注意: Map map ,而物理表中一个 Ingeger 字段,一个 VARCHAR 字段, MyBatis 会自己做类型映射
相关推荐: jdbc通用查询通过map替代实体 ibatis dao的封装讨论(欢迎拍装) 介绍DynamicQueryTool,一个用于解决“拼装动态查询”的小工具。 ibatis查询返回java.util.HashMap结果列表 ibatis中动态查询返回字段返回用resultClass="java.util.HashMap" 的问题 ibatis resultclass "java.util.hashmap" 缓存 ibatis中配置parameterClass="java.util.HashMap"的用法 ibatis中动态查询表返回用resultClass="java.util.HashMap" 的问题 推荐群组: JSF 更多相关推荐 iBATIS 这两天写代码时,遇到一个问题,要求在DAO层要返回一个java.util.HashMap的结果集,但是平常我们多返回List或者VO,在网上搜索了下,结果找到了这样一个方法,记录如下:DAO的实现类中的代码: return Map getItemNames () { return getSqlMapClientTemplate().queryForMap("getItemNameMap", null, "key", "value"); } SqlMap配置文件中的代码: select SKU, Description from Items 在业务层调用getItemNames()时,返回的结果已经是一个标准的java.util.HashMap了,可以使用其方法 get(String key)来直接获取对应的value,非常方便。 参考地址: http://osdir.com/ml/java.ibatisdb.user/2005-01/msg00336.html
相关推荐: Ibator优化版代码生成过程 Ibator支持分页的plugin ibator改造之返回数据库注释和数据库分页 ibatis自动生成工具ibator及配置文件示例 ibatis的ibatorForEclipse的安装与配置和ibator的错误日志查看 ibatis:使用ibator自动生成代码和配置文件 A code generator for iBATIS Myeclipse 8.5 下 iBATIS 的代码生成插件 ibator安装
推荐群组: struts2
更多相关推荐
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
现在我们着手来写一个ibatis的简单例子.
如果你是使用eclipse开发项目的话,那么,有一个eclipse的插件ibator,可以通过 配置 自动生成java代码sqlmap等,蛮好用。下面先做一个使用ibator插件的例子。
1.使用link方式在线 安装 ibator。
eclipse菜单 help-->
software updates-->
add site-->(填入在线 安装 地址:http://ibatis.apache.org/tools/ibator
-->一直下一步 安装
2.新建一个web工程,导入相应的包,我使用的数据库是ORACLE,所以我需要导入的包是:
ojdbc14.jar或classes12.jar,把ibatis需要的jar包都导进去
此例我导入的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
填入 配置 文件名称,可以随便设置 配置 文件名字。一般为“ibatorConfig.xml”,点确定后就创建好了一个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.将对应 配置 参数替换掉上面的“?”号。我自己的替换文件是这样的:
5.之后我们只需要在这个 配置 文件上点击右键-->点击Generate ibatis artifacts,这样就应该能生成对应的package 和 类了
6.如果出现错误使用一下方式查看错误日志
运行cmd用来查询ibatorConfig.xml中出现的错误日志
java -jar d:\ibator.jar -configfile E:\Workspace\test\src\ibatorConfig.xml -overwrite >>c:\log.log
结贴,折腾了一天,刚发帖就找到原因了,我用了rapid-framework3.9.3,里面的分页plugin可能有问题,再研究下。
相关推荐: mybatis和Spring的集成 整合Mybatis与Spring3 MyBatis3新手上路 Springboot整合MyBatis, yml配置,超详细从mybatis-spring-boot-starter根据源码进行配置,MybatisProperties类中的属性【源码版】) SpringBoot整合MyBatis-Plus3.1详细教程 SpringBoot(十六):SpringBoot整合Mybatis-Plus spring boot集成mybatis-generator-maven-plugin和通用mapper MyBatis-Spring整合 推荐群组: 系统架构与架构应用 更多相关推荐 iBATIS 从网上下载官方mybatis-spring整合示例源代码,整合放上来,如果有必要的朋友可以下载,这里说的已经很全了,最好是下载官方相关文档来看。
相关推荐: ibatis源码学习(三)参数和结果的映射原理 spring ibatis clob ibatis经典示例 mule进阶之ibatis component iBATIS入门知识进阶四 iBatis高级应用 ibatis学习进阶 iBATIS SQL Maps之Result Map属性进阶。
推荐群组: JBPM @net
更多相关推荐
iBATIS
Ibatis比较少人使用的配置语法
简单来说,ibatis3虽然没有ognl,不过也支持基本的表达式(看起来有点像el表达式的样子) 上次有个问题,说到两个表单数据(两个javabean),入同一个表,传参就应该不成问题了
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# 当使用复杂配置并且参数带有泛型的时候,使用比较标签有可能导致如下错误: 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);
关于inlineParameterMap
例如#name#(标准配置),#name:NUMBER#(以:分割),#myVar:javaType=int#都是有效的
其中以:分割的有两种方式,#name:jdbcTypeName#,#name:jdbcTypeName:nullvalue#(如果后面还有则会被加到nullvalue上去) 这是老配置方法,个人不推荐使用。
最后一种是新的配置方式,可以带上javaType,jdbcType,mode,nullValue,numericScale,handler等参数(这个文档有详细描述)
jdbcType,javaType和TypeHandler
首先要说明一点的是,配置里边的jdbcType和javaType两个配置参数是为了生成TypeHandler(如果没有指定的话);
查找typeHandler的内部结构是Map
>,其中javaType是一个类,jdbcType是一个字符串; 所以jdbcType其实和数据库的字段类型没什么关系,只要能找到相应的TypeHandler即可(当然通常都会对应上); typeHandler主要是做什么用的呢?无非就是使用jdbc api的时候选择setString/setInt还是getString/getObject之类~~ 只指定resultClass,没有resultMap 如果没有指定resultMap,ibatis会根据parameterClass生成一个AutoResultMap对象; 对于AutoResultMap,里边的每个属性的映射对应的typeHandler是什么? resultClass TypeHandler Map ObjectTypeHandler 原型类型 Bean 相应类对应的typeHandler(javaType=?,jdbcType=null) 会对实例变量名称进行大写并和ResultSetMetaData信息进行对比,最后生成typeHandler(javaType=?,jdbcType=null)
所以使用parameterClass是map的时候,某些字段的处理可能会有点问题,例如oracle的NUMBER类型会被转成BigDecimal类; 只指定parameterClass,没有parameterMap 如果没有指定parameterMap,就会根据配置的sql解析inlineParameterMap; 其中每个参数的TypeHandler如果没有指定,会根据参数的类型来寻找,例如#name,jdbcType=NUMBER# 会根据name计算后的类型来制定javaType 这个typeHandler的好处可以对jdbc api友好,例如对于int默认会采用IntegerTypeHandler,这样会调用PreparedStatement#setInt, 而不是统统setString或者setObject。 通常参数类型和jdbc类型不对应的时候,需要考虑设置typeHandler或者使用更强类型的Bean而不是统统使用map; sqlmap文件"合并"以前还真没用过,感觉这样对于同一个业务的多个应用采用统一的core包还有有些用处的,不错,谢谢分享!
相关推荐: 一个iBatis的demo iBatis2 实现 增 删 改 查 iabtis 测试通过的例子 ibatis2.3.4 + h2 1.3.146数据不能保存的问题 Spring3.0.x API在线参考教程—https://docs.spring.io/spring/docs/ Java工程师成神之路 推荐群组: DI 更多相关推荐 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这行,数据就不会被保存到数据库里去。 从控制台可以看到语句都执行了,但是数据没有被保存进去。 如果H2以Server模式运行,没有出现这个问题。 暂时没找到具体原因
超级潜水艇 写道 注解与xml配置之间有性能上的差异吗? 如果全用annotation感觉要灵活一些 注解适用小型项目,缺点主要是对于同一切入点需要复制,黏贴相同的一段@Transaction,反而来的繁琐。
相关推荐: iBatis分页 iBatis batch处理那些事 ibatis源码学习(一)整体设计和核心流程 从iBatis中得到PreparedStatement 项目开发-iBatis事务源码之SQL执行 ibatis 学习笔记 3 ibatis 中blob的使用 [ibatis]动态映射 推荐群组: IBM WebSphere专区 更多相关推荐 iBATIS iBatis是个好东西,特别是他的动态SQL构建,其实也是选它的原因,除去这个热点,spring的jdbcTemplate更加的 smart。但并不是封装的越完整越好,有时候我们需要用到preparentStatement和resultset,进行一些例外的操作,这时还要用到动态生成的sql和参数的封装,只能从iBatis处想办法了。从现有的iBatis中无法得到这些对象,拿源代码来跟踪一下,改改(开源的好处之一:源代码)。 注意:该改变仅对查询,如果对于更新或其它的,还是调用iBatis的缺省function较好,保证事务的完整和缓存的更新。 水平有限,有什么不对的地方,请大家包涵并指正! 1.对SqlMapClient增加几个接口 /** * 不执行具体的查询,返回一个SessionScope,利用这个sessionScope,返回一个statement * 记得用closeSessionScope来关闭 * @return */ public SessionScope getSessionScope(); /** * 根据传入的sessionScope,关闭 * @param scope */ public void closeSessionScope(SessionScope scope); /** * 你要调用 sessionScope.getSqlMapTxMgr().endTransaction() * sessionScope.cleanup(); * sessionScope.closePreparedStatements() * 释放相关资源 * 或sqlMapClient.closeSessionScope() * * @param session * @param sqlId * @param paramObject * @return * @throws SQLException */ public PreparedStatement makePreparedStatement(SessionScope session,String sqlId,Object paramObject) throws SQLException; 2.SqlMapClientImpl实现上面的接口 /** * 不执行具体的查询,返回一个SessionScope,利用这个sessionScope,调用sqlMapClient.makePreparedStatement返回一个statement * 你要调用 sessionScope.getSqlMapTxMgr().endTransaction() * sessionScope.cleanup(); * sessionScope.closePreparedStatements() * 释放相关资源 * @return */ public SessionScope getSessionScope(){ return this.getLocalSqlMapSession().sessionScope; } /** * 根据传入的sessionScope,关闭 * @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,得到了想要的!
相关推荐: Spring集成iBATIS ibatis事务管理问题--无法实现事务回滚 解决Spring导致iBatis缓存失效问题 Ibatis之缓存插件 强制刷新Ibatis中的缓存(OSCache) ibatis缓存的设置使用 引用iBatis中oscache实现自定义缓存及动态更新技巧 iBATIS 配置oscache缓存 错误(未解决) 推荐群组: DI 更多相关推荐 iBATIS 持久层使用Ibatis,并开启动缓存后台画面可用如下代码强制刷新(根据缓存ID来刷新,不传递缓存参数时,刷新所有缓存) // 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 比如说动态语言支持,ognl表达式,表关系一对多处理,不过对2研究不深。 从学习成本来说,3应该简单些。但现在稳定性应该是2
对于数据库切分,麻烦之一就是分页查询等查询。。没用过guzz ,不知道是否已经解决了。。大概看了下文档,没怎么说明。。稍微网上知道的比较好的数据库切分的中间件是阿里巴巴的amoeba
如果第一种能够满足你的要求,就用第一种;如果不行,就得用回调方法自己写
你的这种事务应用的方法是错误的1、你把事务管理放到了dao层是个错误,dao层不涉及事务方面的东东,你现在的做法的结果是Spring管理的是你的personDAO的事务,在你的测试用例里Spring是对personDAO的save方法进行事务管理,你添加一个person,如果不抛出runtimeexception,事务就会提交,你调用两次save方法就是两次事务,两者是分开的,当然不会回滚 2、事务管理应该放在服务层或业务层,比如说在服务层有个save方法,这个方法里面可以调用多个dao操作,事务管理应该加在服务层对象上。 3、另外要注意的是:你在调用服务层方法时,注入的参数bean应该是动态代理bean
IOC的核心是对于依赖性管理的思想,最好的一句话还是好莱坞原则(当然如果用“依赖注入”更容易理解),反射、动态代理只是实现的工具。
求人不如求己,暴力方法解决,你不是要resource吗?我给你个FileSystemResource.什么?没setPath()?继续暴力,给构造参数........
conf/jdbc.properties 相关推荐: [原创] 如何在Android Market赚钱 part 2 - 免费app附带广告 谈谈android下免费+广告的盈利模式 admob广告看来也能赚钱 ios下应用程序检测admob广告请求返回和点击事件 admob Google AdMob Ads iOS Fundamentals ios如何介入苹果广告_苹果公司的iOS 14广告股票面临新的重大挑战 某Java大佬在地表最强Java企业(阿里)面试总结 推荐群组: Android 更多相关推荐 iOS AdMob目前为止提供了最方便的iPhone app广告集成库.广告的形式是一段320x48的长条横跨屏幕, 点击会scroll出来一个广告网页, 这算一个点击. 首先先去AdMob.com注册帐号, 然后建立你的项目, 每个项目会获得一个ID, 集成AdMob库的时候指定这个ID就可以了. 然后下载AdMob iPhone SDK, 里面包括了所有一切相关的库, 文档和样本. 他们的SDK用到了CoreLocation, CoreGraphics和QuartzCore框架. 集成的方式有三种: 1) 在Interface Builder中放一个320x48的UIView, 加入一个Object, 类型选AdViewController, 然后指定这个controller的view outlet为这个UIView, 就完成了. 2) 在你的程序里, 建立一个AdMob的delegate代理类, 里面只需实现 -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 ^_^ 人品好的就准备开始数钱吧~~~ 目前看来iPhone的banner收入比Android要好, 大概是广告商更喜欢iPhone平台的缘故. *附件是我前几天下雪堆的一个小雪人... -___-#
相关推荐: 大家这么热情,我就献丑了 -- 我的iPhone软件 日本生活旅游必备 日本电车导航地图 - 日本の駅M 很牛的弹出层看看不后悔 ios 上传APP到APP STORE注意事项 当 App Store 遇上电视,开发者的第四代 Apple TV 开箱体验 为Apple ID更换地区,下载非国内APP 六大生态系统的崛起:Apple、Google、Microsoft、Facebook、Amazon、Sony iOS 资源大全 推荐群组: 电脑DIY 更多相关推荐 iOS 刷新历史记录 ,下图第十名是Fifa 10日本top grossing 上 周围都是CAPCOM,TAITO ,Gameloft,Namco等著名公司,有些做梦的感觉。
相关推荐: Mac OS中的mysql驱动 IPHONE 新手入门之前 关于在IOS环境下进行视频通讯开发 iOS 开发 Xcode 8.1创建新项目的配置--详解 XCode编译器里有鬼 – XCodeGhost样本分析 XCode版本介绍和演变史 XCode 下的 iOS 单元测试 不可能不爱的 XCODE 9:最新功能详尽介绍 推荐群组: 高级语言虚拟机 更多相关推荐 iOS 最近升级到Snow Leopard,然后升级XCode到3.2。不是我想升级,是因为我升级完Snow Leopard之后,虽然XCode可以编译iPhone的程序,不过我没办法在我的MacBook上学习Unix编程了,因为/usr/include里面都删空了。升级完之后我才后悔了,因为XCode3.2在SnowLeopard上没有iPhone2.2的模拟器,不过可以为2.2生成程序。 所以如果大家有Legacy的代码要维护,请不要做这样的升级。 当然从这点,大家也可以看到苹果在鼓励大家放弃2.x。不过升级之后的好处也是很多的,我列举几个我体会到的。 [1] 文档系统。我自己是觉得新的文档系统更好用,不过每次按住Option键,然后双击,都会弹出一个框,问你选择文档还是头文件。这个我觉得是可以关掉的,不过现在还没有找到。 [2] 以前如果你写 MyObject *a = [MyObject alloc]init],然后你发现漏写了一个[,你就要回到前面去补。现在 不用了,XCode会自动帮你完成,不信你可以试一下。 [3] 修改公司名字。以前需要用这个命令才可以做到: defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{"ORGANIZATIONNAME" = "ABC";}' 现在有个简单的方法。Ctrl+点击项目,然后选择Get Info,然后在General选项页下面你可以填入你公司的名字: 不过在你做这个修改这前项目里文件的公司名字不会被更改,之后的都会用这个新的。这个功能非常适用。 如果大家发现了什么新的,可以回复我这个帖子。这样大家的经验就可以被累计了。 对了,这里有个不错的帖子: http://stackoverflow.com/questions/146297/what-are-those-little-xcode-tips-tricks-you-wish-you-knew-about-2-years-ago
相关推荐: 求求你们,千万别再说自己是REST了 weblogic8.1 虚拟主机配置问题 How Microsoft Lost the API War Xcode 自动属性生成器(强力推荐) xcode ios gdb iOS开发系列——内购、GameCenter、iCloud、Passbook系统服务开发汇总 HTML5最终会成为iOS和Android替代者吗? 使用 Assets Processor 处理 Xcode @3x @2x图片资源 推荐群组: D语言 更多相关推荐 iOS 一次偶然机会从git上找到,可惜没有添加关注。现在忘记从哪里clone 出来了。 应该是目前最好用的自动补上属性 @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 $/; }; close(SCRIPTFILE); # Look for the class implementation statement if (length($implementationFileContents) && ($implementationFileContents =~ /(\@implementation [_A-Za-z][_A-Za-z0-9]*\n)/)) { my $matchString = $1; my $indexAfterMatch = index($implementationFileContents, $matchString) + length($matchString); # Determine if we want a newline before the synthesize statement $leadingNewline = "\n"; if (substr($implementationFileContents, $indexAfterMatch, 1) eq "\n") { $indexAfterMatch += 1; $leadingNewline = ""; } # Determine if we want a newline after the synthesize statement $trailingNewline = "\n"; if (substr($implementationFileContents, $indexAfterMatch, 11) eq "\@synthesize") { $trailingNewline = ""; } # Create and insert the synthesize statement my $synthesizeStatement; if ($ivarName ne $name) { $synthesizeStatement = $leadingNewline . "\@synthesize " . $name . " = " . $ivarName . ";\n" . $trailingNewline; } else { $synthesizeStatement = $leadingNewline . "\@synthesize " . $name . ";\n" . $trailingNewline; } substr($implementationFileContents, $indexAfterMatch, 0) = $synthesizeStatement; if ($isPointer) { if ($implementationFileContents !~ s#(\(void\)\s*dealloc\s*\{\s*\n)(\s*)#$1$2\[$ivarName release\], $ivarName = nil;\n$2#s) { $implementationFileContents =~ s#(\@end)#\n- (void)dealloc {\n\t[$ivarName release], $ivarName = nil;\n\t[super dealloc];\n}\n$1#s; } } # Use Applescript to replace the contents of the implementation file in Xcode system 'osascript', '-e', $replaceFileContentsScript, $implementationFilePath, $implementationFileContents; } } exit 0; 配置 1.添加到自定义脚本中。 2.INPUT: ENTIRE DOC 3.DIRECTORY:HOME 4.OUTPUT:DISCARD 5.ERRORS:IGNORE 使用: 选中需要生成属性的内容,运行脚本。 enjoy!
相关推荐: javaeye表情汇总 开源软件十杰 介个才是颈椎病的克星 Aspect-Oriented Programming and JBoss 前K条最短路径算法 GNU Hash ELF Sections And GNU-style hash table dnn:深度神经网络_神经网络简介:第2部分 推荐群组: 电脑DIY 更多相关推荐 iOS 感谢大家的支持和帮助。http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=318546714&mt=8 6PHP66PWJWL3 7P37A6HLYN69 XXPHW4HKXJJM WLFNHEJ6RL73 NNT7WR474Y73 9F43PWH3E3WF A74MER9RFWFN A9HNTN3EE6MP XJ4377AELL3F PJANPNKR9NE6
相关推荐: iPhone & iPad高级编程 iPhone开发中的代理与协议(Delegate and Protocol) 大家觉得现在搞iPhone的软件开发有前途(钱途)吗? ios9版本的iphone,不执行网页js iOS 常用第三方库 Appium 实现iPhone真机自动化-常见问题 广州iOS培训——培训相关问题答疑 在经历了6个月的学习后,我终于上架了自己的第一款APP---酷课堂iOS群问答精华整理(201807期) 推荐群组: 图灵俱乐部 更多相关推荐 iOS 很久没有写Blog了,主要是前段时间太忙了。先是在单位上非常非常的忙,在JavaEE之后,我又重新回到了Unix开发的怀抱。现在越来越发现Unix的博大精深和其简单的设计原则,在上面写程序是一件很爽的事情。 我也一直没有离开iPhone的开发,最近在忙几个外包项目,有一个快要上线了,上线之后我会贴出一些截图:)我觉得UI设计还是不错的。通过最近几个月的项目积累和学习,我对SDK3.0有了更多的了解,对iPhone开发的理解也加深了很多。越是这样,我越来越觉得得心应手,而且对iPhone开发的理解也越来越深。 9月12日,我应邀去参加了China-pub和Cocoa China组织的第一届iPhone开发者大会,看到有很多高手在台上分享经验,我也实在觉得惭愧。本来说好了上台去讲的,可是工作太忙了,加上自觉地还没有到可以登台的地步,于是我主动请求换一个人上去讲。在这里真要对组织者Jiang说句Sorry。 那天在会上,我回答了一个iPhone MM的问题。她的问题是,如果在UITableViewCell里面放了一个UITextFiled或者UITextView的控件(我想她用这两个控件都是为了展示信息,不是为了给用户编辑的)。她想Touch这个控件的时候,这个Cell可以获得这个Touch的事件并且响应为Select,而不是那个UITextFiled或者UITextView获得这个响应权。其实方法很简单,只需要把UITextView或者UITextFiled的 userInteractionEnabled设置成FALSE。
相关推荐: 大家这么热情,我就献丑了 -- 我的iPhone软件 关于外包,在日本人眼里,中国还有什么优势可言? 日本生活旅游必备 日本电车导航地图 - 日本の駅M 六大生态系统的崛起:Apple、Google、Microsoft、Facebook、Amazon、Sony 当 App Store 遇上电视,开发者的第四代 Apple TV 开箱体验 iOS资源大全中文版 多年iOS开发经验总结 iPhone手机使用:手机上面的App Store突然变成英文(iTunes也是英文),然后把英文还原成中文的方法 推荐群组: 高级语言虚拟机 更多相关推荐 iOS 随意开发了一个简单程序,没想到这么受欢迎,还上了首页。
lordhong 写道 ankyhe 写道 啊,就是打台球啊, 然后 虐我的Roommate 。很爽啊。 lordhong 写道 呵呵不错啊, 其实自己写自己喜欢的程序是最爽快的事情了.不过我想知道你是怎么用"台球杆"的... Orz... Orz... 我承认... 我想歪了... 你想成什么了~台球杠~
这是一个经典的问题:如何利用有限内存操作大内存图像。Tile-based is the classic solution. 本质就是将图片分为N个小块,每个块就是一个Image Tile. 然后,显示给用户的就是部分tile, not the whole image.
fantasybei 写道 没有iphone还是不行啊,还是去收一台二手的好了,果果一代和二代做开发有区别嘛? 没区别, 3Gs才有真正硬件上的区别...
相关推荐: 手机开发,大虾们过来给个建议 这里的IPHONE分坛好冷清啊 智能手机领域,苹果是否在重复 Mac Vs. PC 时的错误? java后台+微信小程序 实现完整的点餐系统 IOS开发之实现App消息推送(最新) [iOS]应用内支付(内购)的个人开发过程及坑! IOS第一个简单APP iOS开发-审核被拒原因总结[持续更新] 推荐群组: 电脑DIY 更多相关推荐 iOS iPhone无疑是目前最炙热的开发平台之一. 开发者只需要好好的做自己的app, 销售收款物流交易和发布渠道全部由Apple搞定, 收入37开, Apple 3, 开发者7. 比起北美这边运营商动不动就40+%强行占有开发者的收入, Apple算是很厚道了. 无疑, 初期几个很成功的app让一批人赚了第一桶金子. 当然大家都跃跃欲试的时候, iPhone的开发也就有点开始白菜化的趋势. 但毕竟iPhone开发的门槛比较高, 多多少少过滤了一些阿猫阿狗类程序员, 但这里我不谈具体开发事宜, 而是谈谈如何从申请到卖出你的第一个app的流程, 绝对第一手过来人的经验.首先你要买一年$99美刀的开发者license. 在苹果的iPhone dev center有链接. 当然, 不同的地区可能有不同的税率问题. 目前貌似Apple还没有对国内开发, 所以要靠在海外的朋友帮忙搞定一下. license批下来之后当然是要设置自己的开发环境. 洋洋洒洒40多页的设置开发key和license的文档, 任何人看了都会头晕. 而且还不保证你的设置会一次成功. 所以, 唯一的建议就是仔细安装他们的步骤一步一步的做. 如果失败, 从头来过. 这是个极度考验你耐心和人品的过程. 设置成功后 (忘记讲先决条件了, 你需要台Intel主频的Mac, 和一台iPhone, 最起码也要是iPod Touch). 去Apple的developer center下几个sample来试试看. 他们的sample做得都不错. 然后... 读书读文档... 读到你撞墙为止. 切记, 人品值很重要... 保持一颗平常心, 经不起挫折的同学请就此打住, 本人不会对你受挫的自信心会抱有任何的同情. ... 疯狂coding中 ... 做完你自己满意的app后, 提交给Apple审核. 这里这个提交步骤也十分麻烦, 要有很多不同尺寸的截图, 还要一定的格式, N多表格要填好... 接下来就是等审核了. 一般大概是5天时间会有回复. 有什么Apple不满意的你就要顺着他们的意思改. 当然我的两个小app是一次性通过, 人品好确实很重要, 如果人帅的话, 另外加印象分 ^_^ 然后... 是不是开始等着数钱了? 大错特错, Apple竟然还有一个合同审核的步骤. 不管是你卖app还是免费的app, 都要通过他们审核你的纳税合法身份. 这是个人工的步骤... 本人已经等了1个月了... 还没有消息... -__-# 人品值也有over的时候~~~~~ 所以... 做人要低调... 切记...
强,你也太快了吧!你的app审核通过要多长时间?我现在都要2个礼拜,记得以前一个礼拜就好了呀