shouen 2016-04-26
准备使用 SQL Map
SQL Map 架构能应用于设计不好的数据库模型甚至是设计不好的对象模型。尽管如此,
您在设计数据库模型和对象模型时,还是应该遵循最佳的设计原则。这样,您会获得更好的
性能和更简洁清晰的设计方案。
设计最容易开始的地方是分析应用的业务逻辑。分析什么是应用的业务对象,什么是数
据模型以及两者之间的关系。作为快速入门第一个例子,我们使用一个简单的 Java Bean
Person 类。
Person.java package examples.domain; //imports implied…. public class Person { private int id; private String firstName; private String lastName; private Date birthDate; private double weightInKilograms; private double heightInMeters; public int getId () { return id; }
Person 类有了,如何将 Person 类映射成数据表呢?SQL Map 对 Java Bean 和数据表之间
的关系没有限制,如一个数据表映射成一个 Java Bean,或多个表映射成一个 Java Bean,或
多个 Java Bean 映射成一个数据表等。因为使用 SQL Map 您可以充分发挥 SQL 语句的全部
潜力而很少限制。下面这个例子,我们使用一个简单的表,将一个表映射成一个 Java Bean,
Java Bean 和表是一对一的关系。
Person.sql CREATE TABLE PERSON( PER_ID NUMBER (5, 0) NOT NULL, PER_FIRST_NAME VARCHAR (40) NOT NULL, PER_LAST_NAME VARCHAR (40) NOT NULL, PER_BIRTH_DATE DATETIME , PER_WEIGHT_KG NUMBER (4, 2) NOT NULL, PER_HEIGHT_M NUMBER (4, 2) NOT NULL, PRIMARY KEY (PER_ID) )
SQL Map 的配置文件
现在准备好了学习环境,让我们从学习 SQL Map 的配置文件开始,配置文件是 SQL
MAP 的配置信息统一设置的地方。
SQL Map 配置文件是 XML 文件,我们可以它设置各种属性,JDBC DataSource 和 SQL
Map。在配置文件中,可以方便地统一配置 DataSource 不同的实现。SQL Map 框架包括
DataSource 的 iBATIS 实现:SimpleDataSource 类, Jakarta DBCP(Commons),和可通过 JNDI
上下文查找的 DataSource(即应用服务器中的 DataSource)。详细的使用方法在以后的章节
讨论。在本例中,我们使用 Jakarta DBCP。对于上面的例子,配置非常简单,如下所示:
数据源名称(data source name,DSN)是包含了有关某个特定数据库信息的数据结构,这个信息是开放式数据库连接驱动能够连接到数据库上必需的信息。DSN存储在注册表或作为一个单独的文本文件,DSN里面包含的信息有名称、目录和数据库驱动器,以及用户ID和密码(根据DSN的类型)。开发人员为每个数据库创建一个独立的DSN。为了连接到某个数据库,开发人员需要在程序中指定DSN。相反,没有DSN的连接则需要在程序中指定所有必要的信息。
大多数的应用不仅需要从数据库中读取数据,还需要修改数据。我们已有了一个
SELECT 查询语句的 mapped statement 简单例子,下面看看 INSERT,UPDATE 和 DELETE
的 mapped statement 什么样子。幸运的是,它们其实没什么区别。接下来,我们完成 Person
SQL Map 其他部分,以实现修改数据的功能。
好了,我们完成了所有的配置文件和映射文件,就剩下的应用的编码工作了。首先要设
置SQL Map,读入刚创建好的SQL Map XML配置文件。为简化这个工作,可以使用SQL Map
架构中提供的 Resources 类。
String resource = “com/ibatis/example/sql-map-config.xml”; Reader reader = Resources.getResourceAsReader (resource); SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
以上的 SqlMapClient 对象是线程安全,并且应持久生存。对于一个特定的应用,只需
进行一次 SqlMap 配置。因此,它可以作为基类的一个静态对象(即 DAO 对象的基类),或
者,如果您想让它有更大的作用范围,可以把它封装在方便使用的类中。例如:
从数据库读取对象
既然 SqlMap 对象已完成初始化,就可以方便地使用它了。首先,我们用它从数据库中
读取一个 Person 对象。(在本例中,假设 PERSON 表中已存在 10 条记录,PER_ID 从 1 到
10)。
要从数据库中得到一个 Person 对象,只需要 SqlMap 实例,mapped statement 的名字和
一个 Person ID 号。让我们读入 PER_ID 是 5 的 Person 对象。
… SqlMapClient sqlMap = MyAppSqlMapConfig.getSqlMapInstance(); // as coded above … Integer personPk = new Integer(5); Person person = (Person) sqlMap.queryForObject (“getPerson”, personPk);
把对象写入数据库
现在已有了一个从数据库中读出的Person对象,接着修改Person对象的height和weight
属性,并将它写入数据库。
… person.setHeightInMeters(1.83); // person as read from the database above person.setWeightInKilograms(86.36); … sqlMap.update(“updatePerson”, person);
类似地,也可以创建一个新的 Person 对象。
Person newPerson = new Person(); newPerson.setId(11); // you would normally get the ID from a sequence or custom table newPerson.setFirstName(“Clinton”); newPerson.setLastName(“Begin”); newPerson.setBirthDate (null); newPerson.setHeightInMeters(1.83); newPerson.setWeightInKilograms(86.36); … sqlMap.insert (“insertPerson”, newPerson);
快速入门结束了,接下来就要考虑一些新手喜欢出现的错误
1) 在 parameterMap 和 resultMap 中,字段数据类型是 java.sql.Types 类定义的常量名
称。常用的数据类型包括 BLOB,CHAR,CLOB,DATE,LONGVARBINARY,
INTEGER,NULL,NUMERIC,TIME,TIMESTAMP 和 VARCHAR 等。
2) 对于数据表中 NULLBALE 的字段,必须在 parameterMap 和 resultMap 中指定字段
的数据类型。
3) 对于数据类型是 DATE,CLOB 或 BLOB 的字段,最好在 parameterMap 和 resultMap
中指定数据类型。
4) 对于二进制类型的数据,可以将 LONGVARBINARY 映射成 byte[]。
5) 对于文本类型较大的数据,可以将 CLOB 映射成 String。
6) Java Bean 必须拥有缺省的构造器(即无参数的构造器)。
7) Java Bean 最好实现 Serializable 接口,以备应用的进一步扩展。
补充:线程安全:线程安全下定义比较困难。存在很多种定义,如:“一个类在可以被多个线程安全调用时就是线程安全的”。
静态变量:线程非安全。
静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态变量被修改,其他对象均对修改可见,故线程非安全。
实例变量:单例模式(只有一个对象实例存在)线程非安全,非单例线程安全。
实例变量为对象实例私有,在虚拟机的堆中分配,若在系统中只存在一个此对象的实例,在多线程环境下,“犹如”静态变量那样,被某个线程修改后,其他线程对修改均可见,故线程非安全;如果每个线程执行都是在不同的对象中,那对象与对象之间的实例变量的修改将互不影响,故线程安全。
局部变量:线程安全。
每个线程执行时将会把局部变量放在各自栈帧的工作内存中,线程间不共享,故不存在线程安全问题。
如:对于sql语句order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id"。