Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Microsoft Jet Database Engine wikipedia , lookup
Relational algebra wikipedia , lookup
Concurrency control wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Clusterpoint wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Relational model wikipedia , lookup
OBJECTSTUDIO Persistent Object FrameWork User's Guide P40-3222-02 Release information for this manual ObjectStudio Persistent Object FrameWork User's Guide, P40-3222-02, is dated November 1, 2003. This document supports Release 6.9 of ObjectStudio. Cincom Technical Support for ObjectStudio All customers Web: http://supportweb.cincom.com USA customers Phone: 1-800-727-3525 Fax: (513) 612-2000 Attn: ObjectStudio Support Mail: Cincom Systems, Inc. Attn: ObjectStudio Support 55 Merchant Street Cincinnati, OH 45246-3732 USA All: Visit the support links at http://www.cincom.com to find contact information for your nearest Customer Service Center. Outside of USA Using this document This guide describes how to use the Persistent Object FrameWork (POF) with ObjectStudio® to store, retrieve, update, and delete user-defined objects. To use the Persistent Object FrameWork, you should be familiar with the object-oriented approach to software development. If you are using the UniSQL® POF extension, you should have a working knowledge of UniSQL Server database management systems. If you are using the Relational POF extension, you should be familiar with the ObjectStudio development environment, including the Modeling Tool and relational databases. Many of the Relational POF examples in this manual are based on the sample “Sales Order application” on page 194, which is provided with the POF. UniSQL POF examples are provided in “CarSale tutorial” on page 216 and “Paradise demo” on page 229. The information in this guide is organized as follows: Chapter 1—Object-oriented development Summarizes object-oriented development and describes the ObjectStudio development environment. Chapter 2—Persistency and persistency frameworks Defines persistency and describes the relationship of persistence and databases. It also defines persistency frameworks and provides an introduction to the roles of proxies, request brokers, and the transaction manager. Chapter 3—Usage protocol Describes the usage protocol for the Persistent Object FrameWork (POF), including control classes and transaction manager classes. Chapter 4—Framework internals Provides detailed information about the POF request broker, persistency brokers, and the transaction manager. Chapter 5—Benchmarking Describes benchmarking techniques and tools. Chapter 6—Introduction to the Relational POF Introduces the Relational POF, including the framework extension and the Mapping Tool interface. Chapter 7—Building an atlas Describes how to create an atlas, add classes and tables, and prepare to map classes and tables. Chapter 8—Relational POF mapping Describes how to create maps between objects and relational databases. Chapter 9—Completing an application Describes the tasks necessary for completing the application, such as testing and debugging proxies and using object cursors. Chapter 10—Relational POF administration Describes the MAPTOOL.INI file. Chapter 11—Introduction to the UniSQL POF Introduces the UniSQL POF and provides an overview of the development process for applications using the UniSQL POF extension. Chapter 12—UniSQL POF mapping Describes how to map class structures between UniSQL and ObjectStudio. Chapter 13—POF exception handling Describes the POF error messages, detailing specific messages for the Relational POF, for the UniSQL POF, and common messages for both implementations. Appendix A—Sales Order application Describes the object model and database tables provided with the sample Sales Order application, and explains how to map the classes and their attributes to the tables and their columns. Appendix B—CarSale tutorial Describes the CarSale sample application. Appendix C—Paradise demo Describes the Paradise demonstration application. Index Contents Object-oriented development........................................................ 12 Concepts .................................................................................................. 12 Objects............................................................................................... 12 Classes ............................................................................................... 13 Encapsulation ....................................................................................... 13 Relationships ........................................................................................ 14 Developing applications in ObjectStudio ............................................................ 17 Systems design...................................................................................... 17 Three-layer architecture .......................................................................... 18 Summary ............................................................................................. 22 Persistency and persistency frameworks .......................................... 23 Introduction .............................................................................................. 23 Persistency ............................................................................................... 23 Making objects persistent ......................................................................... 23 Persistent storage .................................................................................. 24 Persistent frameworks.................................................................................. 28 Persistent Object FrameWork components .................................................... 28 Proxies ............................................................................................... 32 Persistency Request Broker ....................................................................... 32 Object cursors ...................................................................................... 32 Concurrent access.................................................................................. 33 FrameWork classes ...................................................................................... 34 DynamicPersistencyBroker ........................................................................ 34 MFBroker............................................................................................. 34 MFDatabase.......................................................................................... 34 MFSQLBroker ........................................................................................ 34 AMFSQLGenSpecBroker ............................................................................ 34 MFStatementGeneratorControl................................................................... 35 ObjectCursor ........................................................................................ 35 PersistencyBroker .................................................................................. 35 PersistencyBrokerManagerControl ............................................................... 35 PersistencyRequestBrokerControl ............................................................... 35 PersistentObject.................................................................................... 35 PersistentObjectPoolControl ..................................................................... 35 Persistent Object FrameWork User's Guide, P40-3222-02 Contents 5 PersistentStore ..................................................................................... 36 ScrollableObjectCursor ............................................................................ 36 TransactionManagerControl....................................................................... 36 UFBrokerControl .................................................................................... 36 UFDatabaseControl................................................................................. 36 Usage protocol ........................................................................... 37 Introduction .............................................................................................. 37 Object-retrieval services............................................................................... 38 PersistentObject class methods.................................................................. 39 Examples............................................................................................. 47 Template-retrieval services ........................................................................... 49 PersistentObject instance methods ............................................................. 50 Examples............................................................................................. 52 Persistency services..................................................................................... 53 PersistentObject instance methods ............................................................. 54 Examples............................................................................................. 57 Object cursor services .................................................................................. 58 ObjectCursor instance methods.................................................................. 58 Example ObjectCursor instance method........................................................ 59 Scrollable object cursor services ..................................................................... 60 ScrollableObjectCursor instance methods...................................................... 60 Example ScrollableObjectCursor instance method............................................ 61 Transaction manager services......................................................................... 62 Transaction manager instance variable......................................................... 62 Transaction manager instance methods ........................................................ 62 Example TransactionManager instance method ............................................... 62 Object pool services .................................................................................... 63 Framework internals ................................................................... 65 Introduction .............................................................................................. 65 Persistency Request Broker............................................................................ 65 Persistency brokers ..................................................................................... 67 Relational POF broker ............................................................................. 67 UniSQL POF broker ................................................................................. 69 Transaction manager ................................................................................... 70 POF and transactions .............................................................................. 71 Errors ................................................................................................. 72 Multiple transactions .............................................................................. 72 Using proxies ............................................................................................. 73 Proxy basics ......................................................................................... 73 Implementing proxies.............................................................................. 76 Object pool............................................................................................... 79 Persistent Object FrameWork User's Guide, P40-3222-02 Contents 6 Benchmarking ............................................................................ 81 Benchmarking application ............................................................................. 81 Initiating benchmarking ........................................................................... 82 Activating benchmarking.......................................................................... 84 Deactivating benchmarking ....................................................................... 84 Resetting benchmarking........................................................................... 84 Refreshing the benchmarking data .............................................................. 85 Benchmark class ......................................................................................... 86 Benchmark class methods......................................................................... 86 Examples............................................................................................. 90 Introduction to the Relational POF .................................................. 91 The Relational POF...................................................................................... 91 FrameWork extension.............................................................................. 92 Mapping Tool interface ............................................................................ 92 The Mapping Tool interface ........................................................................... 93 Installation requirements ......................................................................... 93 Installing the Mapping Tool ....................................................................... 94 Uninstalling the Mapping Tool.................................................................... 95 Starting the Mapping Tool......................................................................... 96 Creating classes..................................................................................... 97 Creating tables ..................................................................................... 98 Preparing classes ................................................................................... 98 Preparing tables .................................................................................... 99 Loading database support........................................................................ 100 Loading the Mapping Tool........................................................................ 100 Saving an image ................................................................................... 101 Loading classes .................................................................................... 102 Verifying class information ...................................................................... 103 Starting the Mapping Tool........................................................................ 105 Running the sample Sales Order application.................................................. 105 Mapping Tool user interface basics.................................................................. 106 List boxes ........................................................................................... 106 Menus................................................................................................ 111 Toolbar.............................................................................................. 112 Building an atlas ........................................................................ 113 Atlas basics .............................................................................................. 113 Multiple atlases .................................................................................... 113 Databases and qualifiers ......................................................................... 113 Steps for building an atlas ....................................................................... 114 Setting atlas mapping preferences .................................................................. 115 Creating an atlas ....................................................................................... 117 Persistent Object FrameWork User's Guide, P40-3222-02 Contents 7 Specifying a database ................................................................................. 117 Adding classes to the atlas............................................................................ 118 Determining which classes to add .............................................................. 118 Adding classes...................................................................................... 119 Setting class preferences ........................................................................ 120 Using object queries .............................................................................. 122 Adding tables to the atlas ............................................................................ 123 Specifying a primary key .............................................................................. 124 Managing concurrency ................................................................................. 126 Implementing concurrency management ...................................................... 126 Concurrency classes and methods .............................................................. 129 Opening an atlas........................................................................................ 130 Editing an atlas ......................................................................................... 131 Removing a class .................................................................................. 131 Removing a table .................................................................................. 131 Renaming an atlas................................................................................. 132 Changing database associations................................................................. 132 Synchronizing an atlas ................................................................................. 133 Closing an atlas ......................................................................................... 134 Deleting an atlas ....................................................................................... 134 Relational POF mapping............................................................... 135 Mapping basics .......................................................................................... 135 Map types ........................................................................................... 135 Mapping order...................................................................................... 137 Joins between tables ............................................................................. 138 Attribute data type conversion ................................................................. 139 Creating maps........................................................................................... 141 Class map ........................................................................................... 141 Primitive attribute map .......................................................................... 142 Reference attribute map......................................................................... 144 Collapsed gen-spec map.......................................................................... 147 Inherited gen-spec map .......................................................................... 150 Partitioned class map............................................................................. 150 Lookup table map ................................................................................. 152 Dependent object map ........................................................................... 156 Saving an atlas .......................................................................................... 159 Using defaults ...................................................................................... 160 Using optional settings ........................................................................... 163 Printing mapping information ........................................................................ 166 Report types ....................................................................................... 166 Generating reports ................................................................................ 168 Persistent Object FrameWork User's Guide, P40-3222-02 Contents 8 Completing an application............................................................ 169 Saving and deleting objects .......................................................................... 169 Available methods................................................................................. 170 Understanding which methods to use .......................................................... 170 Testing maps ............................................................................................ 172 Reasons for testing ................................................................................ 172 Using the object cursor for testing ............................................................. 173 Deploying an application .............................................................................. 175 Preparing the application ........................................................................ 175 Saving an image ................................................................................... 175 Relational POF administration....................................................... 176 MAPTOOL.INI file ....................................................................................... 176 Mapping Tool parameters ........................................................................ 176 Synchronization parameters ..................................................................... 177 Introduction to the UniSQL POF..................................................... 178 Purpose .................................................................................................. 178 Development process overview ...................................................................... 179 Development procedure.......................................................................... 179 UniSQL POF sample applications ................................................................ 183 Database connections ................................................................................. 184 logon ................................................................................................ 184 logoff ................................................................................................ 184 UniSQL POF mapping .................................................................. 185 Mapping overview ...................................................................................... 185 Creating a map class................................................................................... 187 Persistent Object FrameWork User's Guide, P40-3222-02 Contents 9 POF exception handling............................................................... 189 Common exceptions ................................................................................... 189 POFAbstractClassError ............................................................................ 189 POFAbstractError .................................................................................. 189 POFCursorAlreadyOpen ........................................................................... 189 POFCursorNotOpen ................................................................................ 189 POFCursorNotPositioned ......................................................................... 189 POFError ............................................................................................ 189 POFHasDifferentBrokersForClass................................................................ 190 POFNoActiveTransaction ......................................................................... 190 POFNoBrokerForClass ............................................................................. 190 POFNoBrokerForService .......................................................................... 190 POFNotFound....................................................................................... 190 POFObjectNotPersistent ......................................................................... 190 Relational POF exceptions ............................................................................ 191 POFIllegalOperation............................................................................... 191 POFObjectHasChanged ........................................................................... 191 POFNoMapForClass ................................................................................ 191 POFNoMappedTablesForClass.................................................................... 191 POFNotUnique ..................................................................................... 191 POFNoValueForColumn ........................................................................... 191 POFNoValueForConstantColumn ................................................................ 191 UniSQL POF exceptions ................................................................................ 192 POFUFError ......................................................................................... 192 POFUFLogonError.................................................................................. 192 POFUFMappingError ............................................................................... 192 POFUFParseError .................................................................................. 193 Sales Order application ............................................................... 194 Sample application overview ......................................................................... 194 Object model structure ............................................................................... 195 SALESORDER database tables......................................................................... 197 Commercial......................................................................................... 198 LineItem ............................................................................................ 199 Product.............................................................................................. 203 RepTerritory........................................................................................ 204 SalesOrder .......................................................................................... 206 SalesRep ............................................................................................ 207 SalesRepExtra ...................................................................................... 207 Territory ............................................................................................ 208 VAR .................................................................................................. 209 Persistent Object FrameWork User's Guide, P40-3222-02 Contents 10 Creating the sample application atlas .............................................................. 210 Defining primary keys............................................................................. 210 Mapping classes to tables ........................................................................ 210 Defining dependent objects ..................................................................... 215 Mapping reference attributes ................................................................... 215 CarSale tutorial ......................................................................... 216 Before you begin ....................................................................................... 216 Tutorial description .................................................................................... 217 Creating a database schema.......................................................................... 219 Creating Smalltalk classes ............................................................................ 221 Mapping a database schema to an object hierarchy.............................................. 223 Logging on to the database ........................................................................... 226 Creating an object instance .......................................................................... 227 Retrieving information from the database ......................................................... 228 Logging off from the database ....................................................................... 228 Paradise demo .......................................................................... 229 Before you begin ....................................................................................... 229 Application description................................................................................ 229 Loading the Paradise demo ........................................................................... 231 Adding an instance ..................................................................................... 235 Deleting an instance ................................................................................... 237 Selecting specific instances .......................................................................... 238 Setting instance attributes ........................................................................... 243 Location............................................................................................. 244 Rates ................................................................................................ 245 Facilities ............................................................................................ 246 Restrictions......................................................................................... 247 Activities............................................................................................ 248 Rooms ............................................................................................... 251 Saving instance attributes ............................................................................ 257 Index ...................................................................................... 258 Persistent Object FrameWork User's Guide, P40-3222-02 Contents 11 1 Object-oriented development Concepts The object-oriented approach is based on the idea that in the real world, the basic unit of existence and activity is an object. Objects An object is a structure that represents a real-world entity and the entity’s set of behaviors. It consists of attributes (data) and methods (behavior). The following figure shows a common way of representing an object: Object Behaviors Data When you define an object, you analyze a real-world entity and determine what it does. For example, in a sales situation, a customer is an object that purchases a product. Each customer object is responsible for knowing its name, address, and identification number. It can purchase products, return products, and pay for purchases. A customer purchase pay name address id number ... ... return Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Concepts 12 Classes An object is an instance of a class. The class describes the attributes and operations that are common to all of the instances. For example, if you have several customer objects, you can create a Customer class that provides all of the data and behaviors the customers share. Although some products and books consider the terms class and object to be interchangeable, in the ObjectStudio development environment, object always refers to an instance of a class. Encapsulation An object contains all information about the object, including its characteristics and its range of possible actions. The object and its behaviors form a single package. This concept is called encapsulation. Only the object’s own methods can access data in an object. Other objects that need access to the data send a message to the object, which executes a method and provides the requested response. Restricting access to an object’s data in this way provides several benefits: ♦ It insulates the object from incorrect handling by other objects. ♦ It insulates other objects from having to know the object’s internal structure. ♦ It makes changing the application processing simple. Encapsulation localizes changes to the data. Most behavior changes require changing only a few objects. In object-oriented applications, unlike conventional applications, you never have to hunt through the code of a large complex system to find all routines that access a certain item of data. Instead, all methods are in one place—in the object. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Concepts 13 Relationships The object-oriented approach recognizes that objects in the real world are related to one another and have three kinds of relationships: ♦ Association ♦ Aggregation (sometimes referred to as whole-part) ♦ Generalization-specialization Association An association is a functional relationship between two objects, sometimes called a weak association between objects. The objects work together in some way. The object SalesOrder and the object Customer are related functionally, because in the real world a customer can place one or more sales orders. Two objects related by association may have nothing in common structurally. Association relationships can be: ♦ One-to-one ♦ One-to-many ♦ Many-to-many The following figure shows the one-to-many association between Customer and SalesOrder: Customer 1 SalesOrder SalesOrder customer: Customer lineItem: IdentitySet orderDate: Date orderNumber: String orderSys: OrderSys salesRep: SalesRep Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Concepts address: Address customerId: String name: String salesOrder: IdentitySet territory: Territory Customer 0..* 14 Aggregation An aggregation is a whole-part relationship, also called a strong association. One object (for example, a car) can be an aggregation of several other objects (a motor, a body, wheels, doors, etc.). The aggregation exists as an object, and its component parts also can be treated as separate objects, each with a different structure and set of behaviors. When an aggregated object ceases to exist, all of its components also cease to exist. Objects related by aggregation have a structural and a functional relationship. However, the part classes in an aggregation do not inherit the attributes or methods of the whole class. In the sample Sales Order application (Appendix A), there is an aggregation relationship between the SalesOrder and LineItem classes. A sales order is composed of one or more line items. The aggregation relationship is shown in the following figure: SalesOrder customer: Customer lineItem: IdentitySet orderDate: Date orderNumber: String orderSys: OrderSys salesRep: SalesRep LineItem 0..1 SalesOrder 0..* LineItem lineNumber: String product: Product quantity: SmallInteger salesOrder: SalesOrder Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Concepts 15 Generalization-specialization A generalization-specialization (gen-spec) relationship is a structural relationship in which one or more subclasses (child objects) inherit characteristics and behaviors from a superclass (parent object). The generalization, or superclass, has a basic set of characteristics and behaviors (attributes and methods) that are inherited by all of its specialization, or subclass, objects. Each subclass object has additional characteristics and behaviors that are unique and not shared with the other subclass objects. This separation allows shared attributes and behaviors to reside in the superclass, and provides a way for each subclass to add unique, specialized attributes and methods. In the Sales Order model, there are two gen-spec relationships. The subclasses ServiceProduct and SoftwareProduct inherit the attributes and methods of the abstract superclass Product. The subclasses VAR and Corporate inherit the attributes and methods of the abstract superclass Customer. The following figure shows Customer and its subclasses VAR and Corporate: Customer address: Address customerId: String name: String salesOrder: IdentitySet territory: Territory Corporate VAR discount: Float In some gen-spec relationships, the superclass is abstract. That is, the application never creates an instance of the superclass; it is used only to centralize the shared attributes and methods of the subclasses. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Concepts 16 Developing applications in ObjectStudio Systems design Object-oriented systems design involves two processes: ♦ Modeling objects. You model objects as they exist, behave, and interact in the real world. A model is a group of objects that are related to one another logically or functionally. A model includes all objects that are relevant to solving a particular business problem or a set of related problems. ♦ Building systems. You build systems that implement those objects that you have modeled and their behaviors and interactions. When you build a system, you define how the objects work in their environment, particularly their relationships to other objects. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Developing applications in ObjectStudio 17 Three-layer architecture Many successful object-oriented applications are based upon a three-layer architecture. In this model, objects are separated into three layers: ♦ View ♦ Business ♦ Access The following figure shows how ObjectStudio tools work together to create the three layers in an application: View Layer ObjectStudio Developer Designer UI UI UI Business Layer Modeling Tool ObjectStudio Classes Object Model Access Layer Persistent Object Framework Persistency Request Broker Persistency Framework Transaction Manager Persistent Store UniSQL Database Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Developing applications in ObjectStudio Relational Database 18 View layer The view layer contains classes that control and display the application interface. Use the ObjectStudio Designer to design the user interface and create the view layer. It enables you to link the user’s input events to methods in the controller objects. ObjectStudio provides a full-featured, flexible environment for creating and executing object-oriented applications. Within ObjectStudio, you use the Smalltalk language to write custom methods for classes. When you use the Modeling Tool to generate business object classes, the Designer is extended. That is, the Designer provides automated facilities for creating user interfaces that are based on the generated business object classes. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Developing applications in ObjectStudio 19 Business layer The business layer consists of classes that represent the business model. A business model captures the static and dynamic relationships between a collection of business objects or classes. Business objects capture both the characteristics and behaviors of real-world business entities, such as customers, orders, employees, or accounts. In the business layer, classes are business objects. The following figure illustrates the structure of a business model: Class2 Class1 1 1 Class1 Class2 Class3 1 1 Class2 Class3 0..1 Class6 Class1 Class6 0..* Class4 Class5 For example, if you are designing a system to track store profits for a group of retail stores, the business layer might include a Store class, an Employee class, and perhaps inventory item classes and subclasses. These business objects implement the attributes of their real-life counterparts (for Store, aspects such as address, manager, sales, square feet) and their behavior (such as the ability to compute sales per square foot). You can use the Modeling Tool to create the business layer. The ObjectStudio Modeling Tool allows you to build a complete visual model of your business by creating objects, called classes, and defining their relationships. You then can use the Modeling Tool to generate Smalltalk code for these classes, with all basic object-manipulation methods already defined. Smalltalk code includes new, initialize, and destroy methods for each class, as well as attribute accessor methods and methods that maintain the relationships among class instances. You can also write methods in Smalltalk to define object behavior that is specific to your business. The Modeling Tool can synchronize the business classes that are in the Modeling Tool with your application classes in the development environment. You can easily update the model as your business changes, and you can propagate those changes directly into the ObjectStudio application. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Developing applications in ObjectStudio 20 Access layer The access layer is the interface to the databases and other external systems that interact with the application. Access layer objects can translate between the format of these external data sources and the business objects whose data they contain. Use one of the following frameworks to create the access layer: ♦ Relational POF. When you create the access layer with the Relational POF, the access layer consists of an atlas and request brokers. The atlas contains all information the Relational POF requires in order to handle database requests from the application. In addition to helping you create the access layer, the Relational POF allows you to convert relational data into objects by assembling the attributes in the ObjectStudio development environment. Instead of hard coding SQL statements to application and user interface objects, the Relational POF makes applications appear to be connected to an object database, without requiring you to program any SQL statements. ♦ UniSQL POF. To create an access layer using the UniSQL POF, you first design a business model using the Modeling Tool. Then you generate a database schema, using the UniSQL Schema Generator, and Smalltalk classes. In addition, you may need a class map that resolves keyword conflicts (if any) between the Smalltalk class structure and the UniSQL database class structure (see “Mapping overview” on page 185). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Developing applications in ObjectStudio 21 Summary ObjectStudio tools work together to create object-oriented client/server applications. There is a division of responsibility among the ObjectStudio components: ♦ Modeling Tool. Allows you to focus on building the business model. The Modeling Tool generates code for classes and relationships. You link this code into the ObjectStudio Smalltalk development environment. ♦ Persistent Object Framework. Links the business model to the database. ♦ ObjectStudio Designer. Automates the generation of the application’s user interface. When you use the ObjectStudio tools together, the tools generate about 80% of your application’s code. You build the other 20%, which is the business logic. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Object-oriented development Section: Developing applications in ObjectStudio 22 2 Persistency and persistency frameworks Introduction This chapter introduces the concept of persistency and describes object and database interaction. It also describes persistency frameworks and provides a brief overview of the framework components. Persistency In programming languages such as Smalltalk, you create and manipulate objects. These objects reside in memory while the program is running. When the program ends, the objects cease to exist, and memory is freed for use by the operating system. These objects are transient objects. In contrast, persistent objects continue to exist after the program ends. For this persistence to occur, the objects must be stored in persistent storage, such as a file or database. Because databases address issues such as concurrent access by multiple users, security, and backup facilities, a database is the obvious choice for persistent storage. Making objects persistent As previously described, an object consists of attributes (data), and methods (behavior). For an object to become persistent, its attributes and methods must be stored. An object’s methods are stored in the program as part of a class. You can store the object’s data (state or attributes) in a database. When you retrieve the object from persistent storage, you can update some of the object’s state, or delete the object when it is no longer needed. The POF provides the facilities to store, retrieve, update, and delete the object data in a database. For more information about persistent objects, refer to Object Persistence: Beyond Object-Oriented Databases (Prentice Hall) by Roger Sessions. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Introduction 23 Persistent storage Before creating a persistent object, you must know how to make objects persistent and the ways you can store the objects. Objects are persistent when they are stored. There are two basic types of persistent stores that can maintain objects: ♦ Files. Store the object, but they are limiting in size and accessibility. ♦ Databases. Provide concurrency management, multiple-user accessibility, and mission-critical features found in most databases. The primary types of databases used to store objects are object and relational databases. Object databases Because objects model the real world and result in applications that are easy to maintain, a good way to make those objects persistent is to store them in an object database, such as UniSQL Server. An object database can store the whole object, not just the object’s data, which means that the object and its methods can be stored in one place by storing references to other objects. These references allow the database to store the object structure, complete with all of its objects and their relations. The Persistent Object FrameWork, however, assumes that you are storing most of the object behavior in ObjectStudio. The advantage of using an object database is flexibility. For example, you can define your own data types—you are not limited to predefined, standard data types such as dates, numbers, and text. Another example of an object database’s flexibility is that you can define subclasses to handle exceptions. Traditional databases do not allow you to enter data that does not conform to the defined data type. Object databases allow you to store unusual data without affecting the previously stored data. For more information about object databases, refer to: ♦ Object-Oriented Technology: A Manager’s Guide (Addison-Wesley), David Taylor ♦ Introduction to Object-Oriented Databases (MIT Press), Won Kim ♦ Object Data Management (Addison-Wesley), R.G.G. Cattell ♦ Object-Oriented Databases with Applications to CASE, Networks, and VLSI CAD (Prentice Hall), Rajiv Gupta Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistency 24 Relational databases Although object databases work well for storing object-oriented applications, many companies currently have large investments in relational databases. Relational databases can hold large volumes of data and offer backup and recovery procedures that fulfill the requirements of organizations with vast amounts of legacy information. Relational databases store data in tables. A table is a collection of columns and rows. All values in a given column must have the same data type (or domain). Each column is defined to contain a specific item of information. A table consists of one or more rows, where each row has a value in each column. A row contains information about one item. A table contains information about many identically structured items. Relational databases employ the following concepts: ♦ Normalization. Normalization is a procedural calculus with goals to ensure good database design. To conform to first normal form, all tables in a database must be flat, with one value per attribute in every row. Second through fifth normal forms successively refine the database structure. Normalization preserves and protects data integrity but often splits objects among several tables in a relational database. ♦ Table joins. Related information about a single item can be stored in more than one table. Related tables can be connected, or joined, to one another at run time, so that the application can access all related information about one or more items. Two tables are considered related if the values in a column in one table also occur in a column in another table. ♦ Keys. The column used to join one table to another is called the key. The primary key is the column whose values uniquely identify rows in that table. A foreign key is a column whose values are not unique but correspond to the values of the primary key in a related table. A table has a composite primary key if values from two or more columns are needed to uniquely identify each record. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistency 25 The following figure shows a table join from the sample Sales Order application: SalesOrder Table LineItem Table orderNo orderDate lineOrderNo 1 1,m lineNumber ... ... ... ... There is a one-to-many relationship between the tables, which means that there can be many line items in a sales order but only one sales order for a line item. The primary key for the SalesOrder table is orderNo. The primary key for the LineItem table is a composite primary key made up of the lineOrderNo and lineNumber columns. The lineOrderNo column in the LineItem table is also a foreign key because it corresponds to the orderNo column in the SalesOrder table. For more information about the Sales Order application table structure, see “SALESORDER database tables” on page 197. Suggested reading. For additional information about relational database theory, refer to An Introduction to Database Systems, Volume I; Relational Database: Selected Writings; and Relational Database Writings 1985–1989 (Addison-Wesley), all by C. J. Date. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistency 26 Bridging the gap for relational databases. The previous sections describe the differences between objects and the object-oriented approach and the relational database approach. Understanding the challenge of mapping between objects and relational tables allows you to understand the benefits provided by the Relational POF, how it works, and why. Using the object-oriented approach results in an object model with one structure; implementing relational database techniques results in a database with another structure for the same application. To resolve these differences and correctly map objects to tables, you must specify how the tables in a relational database are joined. When an ObjectStudio application requests objects from the database, the Mapping Tool joins tables as needed to assemble all related data needed to build each object. The Relational POF does not explicitly address any of the other behavioral differences between objects and relational databases. You must determine how to implement the behavior of the existing system as object methods when reengineering a legacy database application. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistency 27 Persistent frameworks A framework is a set of classes that work together to perform designated functions. A persistency framework is a set of classes that work together to make application objects persistent, allowing you to store, retrieve, update, and delete user-defined objects. The framework should support database access-related services, such as concurrency and transaction management, and should complement the functionality of the persistent store to provide full persistent services. The primary benefits of using a persistent framework are: ♦ Database access is encapsulated. Database access is shielded from the application, which makes it easier to change the underlying database. ♦ Database access is simplified. You can more easily implement database access features in your applications. ♦ Framework is extensible. You can incorporate your own classes and features into the framework. Persistent Object FrameWork components The Persistent Object FrameWork for Smalltalk consists of: ♦ Abstract framework ♦ Relational framework extension, referred to as the Relational POF ♦ UniSQL framework extension, referred to as the UniSQL POF Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistent frameworks 28 Abstract framework The Abstract framework handles the basic tasks required to make objects persistent. The framework extensions handle the database-specific implementation. In the following figure, the shaded classes are the classes provided in the Abstract framework. The white classes show where the user-defined classes fit into the framework. PersistentObject Customer Order PersistencyRequestBroker PersistencyBrokerManager ... ObjectCursor PersistencyBroker ScrollableObjectCursor TransactionManager PersistencyStore One class from the Abstract framework, PersistentObjectPoolControl, does not appear in this figure. The reason is because it does not directly interact with any one class of the framework and, therefore, does not have any relationship to the other classes. For class descriptions, see “FrameWork classes” on page 34. For information about using the framework, see “Introduction to the Relational POF” on page 91 and “Introduction to the UniSQL POF” on page 178. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistent frameworks 29 Relational framework extension The Relational Persistent Object FrameWork (Relational POF) consists of an extension to the Abstract framework and the ObjectStudio Mapping Tool interface. The Mapping Tool provides an interface for the mapping process involved in bridging the gap between a relational database and Smalltalk. The Mapping tool cannot be used with the repository-based version of ObjectStudio; it is only available with the file-based version. The following figure shows where the Relational POF extension fits into the Abstract framework. The white classes are the classes provided in the Abstract framework. The shaded classes are the Relational framework classes. PersistentObject PersistencyRequestBroker PersistencyBrokerManager ObjectCursor PersistencyBroker TransactionManager MFBroker ScrollableObjectCursor PersistencyStore MFStatementGenerator MFDatabase For class descriptions, see “FrameWork classes” on page 34. For more information, see “Introduction to the Relational POF” on page 91. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistent frameworks 30 UniSQL framework extension The UniSQL Persistent Object FrameWork (UniSQL POF) consists of an extension to the Abstract framework that interfaces directly with the UniSQL API to perform the necessary mapping services. The UniSQL POF also includes a Schema Generator that helps in the creation of a UniSQL database schema based on a model from the ObjectStudio Modeling Tool. The following figure shows where the UniSQL POF extension fits into the Abstract framework. The white classes are the classes provided in the Abstract framework. The shaded classes are the UniSQL framework classes. PersistentObject PersistencyRequestBroker PersistencyBrokerManager PersistencyBroker ObjectCursor TransactionManager DynamicPersistencyBroker ScrollableObjectCursor PersistencyStore UFBroker UFDatabase For class descriptions, see “FrameWork classes” on page 34. For more information, see “Introduction to the Relational POF” on page 91. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistent frameworks 31 Proxies If you are using a relational database in your access layer, you can use proxy objects to continue to think in terms of objects without sacrificing performance or adding complexity. A proxy object represents a real object that has not yet been retrieved from persistent storage (see “Using proxies” on page 73). Persistency Request Broker All object manipulation in the POF is handled by the Persistency Request Broker. The Persistency Request Broker is a class that manages requests between application objects and their persistent storage. When an application issues a request to perform an action for an object, the Persistency Request Broker uses the other brokers to perform the requested action. Object cursors An object cursor is a cursor that provides a window into a result set located on the server. It functions the same as a typical database cursor except that it returns Smalltalk objects instead of data in the result set. The result set can be all of the objects in a class or the result of a query. Object cursors are an efficient way to view large sets of data because they allow you to page through a result set on the database server and only download the data you need. The following figure shows an object cursor: Object Cursor Table ff f Object Table Table A scrollable object cursor provides the same functionality as an object cursor, but it also allows you to move backwards through the data and change the cursor position. The POF implements an object cursor (ObjectCursor) and a scrollable object cursor (ScrollableObjectCursor). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistent frameworks 32 Concurrent access Because multiple users and applications access databases, database applications require concurrency management to prevent conflicts. This section introduces two methods used to handle concurrency. Locking One way to handle concurrency is to use one of the following types of locking: ♦ Pessimistic locking. Pessimistic locking allows only one user at a time to request and update data. Other users can view the data in read-only mode while it is locked. Unfortunately, pessimistic locking is complex and introduces the possibility of deadlocks. Deadlocks occur when two transactions are waiting for locks held by each other to be released. ♦ Optimistic locking. Optimistic locking locks data only immediately before data is written back to the database. If the data on the database is the same as the data that was originally retrieved, the update is performed and the lock is released. If the data has changed, an exception is returned, and the application developer must handle it directly. The POF implements optimistic locking. Optimistic locking is an efficient way to handle concurrency in applications where large volumes of data are moved between the database and the application level, and where data is retained for a long time. Transaction manager Another way to handle concurrency is to use a transaction manager. A transaction is a logical unit of work in an application. Applications issue multiple transaction requests when they run. Most databases use transaction managers to handle the proper execution of the transactions. Transaction managers synchronize multiple transactions so that they occur at the same time. This synchronization lets multiple users or applications access the database. For more information about transaction managers, see “Transaction manager” on page 70. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: Persistent frameworks 33 FrameWork classes This section briefly describes the classes that compose the Abstract, Relational, and UniSQL frameworks. DynamicPersistencyBroker Defines the POF’s standard dynamic broker protocol. All compliant dynamic brokers must be a subclass of this class and implement all of the necessary methods. The DynamicPersistencyBroker class is simply a protocol specification and does not add any behavior. UFBroker is an example of a DynamicPersistencyBroker subclass. MFBroker Implements the methods necessary to support the POF abstraction for relational databases. MFDatabase Provides the mechanisms necessary for connecting to a relational database. MFSQLBroker This is provided for backward compatibility only. Implements the methods necessary to interface with an SQL database. The broker implemented in the POF provides backward compatibility with prior versions of the ObjectStudio Mapping Tool. AMFSQLGenSpecBroker This is provided for backward compatibility only. Implements the methods necessary to use gen-spec classes with an SQL database. The broker implemented in the POF provides backward compatibility with prior versions of the ObjectStudio Mapping Tool. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: FrameWork classes 34 MFStatementGeneratorControl Generates all necessary SQL statements for the brokers in the Relational extension (Relational POF). It is a singleton class. ObjectCursor Functions as a typical database cursor, but returns real Smalltalk objects such as the different find methods. ObjectCursor can only move forward in a result set. For moving backward and positioning functionality, use the ScrollableObjectCursor. PersistencyBroker Defines the standard broker protocol in the POF. All compliant brokers must be a subclass of this class and implement all necessary methods. The PersistencyBroker class is simply a protocol specification and does not add any behavior. MFBroker is an example of a PersistencyBroker subclass. PersistencyBrokerManagerControl Handles the interface between Smalltalk classes, services, and brokers. It knows which broker to use for a specific service on a specific class. It is a singleton class. PersistencyRequestBrokerControl Directs traffic in the POF. It delegates all requests to the specific brokers as defined in the PersistencyBrokerManager. Use the interface defined by PersistentObject instead of using this class directly. It is a singleton class. PersistentObject Exists as the root of all persistent objects in a given application and implements all behavior needed for persistency. PersistentObject does not perform any tasks itself but delegates the tasks to the PersistencyRequestBroker. The protocol between these two objects has been standardized. PersistentObjectPoolControl Handles integrity in the Smalltalk image. The pool will, if enabled, make sure that only one instance of any given row or object (UniSQL) in the database exists in the image. It is a singleton class. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: FrameWork classes 35 PersistentStore Defines the standard transactional resource protocol in the POF. All compliant resources must be a subclass of this class and must implement all of the necessary methods. The PersistentStore class functions as a protocol specification. ScrollableObjectCursor Randomly accesses large sets of data without having to store all of the data in memory at one time. TransactionManagerControl Handles transactions for the framework. Either the POF can handle these transactions internally (the default), or you can use this interface to develop an external implementation. TransactionManager is a singleton interface for the whole application-development environment. UFBrokerControl Implements the methods necessary to support the POF abstraction for the UniSQL database. It utilizes UniSQLLibrary to gain access to the UniSQL DLLs directly. It is a singleton class. UFDatabaseControl Provides the mechanisms necessary for connecting to the UniSQL database. It is a singleton class. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Persistency and persistency frameworks Section: FrameWork classes 36 3 Usage protocol Introduction This chapter describes the services and methods in the POF usage protocol and documents the POF standard abstraction persistent services in the following categories: ♦ Object-retrieval ♦ Template-retrieval ♦ Persistency ♦ Object cursor ♦ Scrollable object cursor ♦ Transaction manager ♦ Object pool The first three types of services are persistent services. Persistent services are high-level methods that manage object persistence. The next two types of services describe the methods for ObjectCursor and ScrollableObjectCursor. The next type describes the methods for the transaction manager. The last type describes the methods for the PersistentObjectPool class. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Introduction 37 Object-retrieval services You use the object-retrieval services to return objects from persistent storage. You can retrieve the data in ordered collections or by using an object cursor. For methods that retrieve objects from persistent storage as an ordered collection, you can set options such as a limit on how many objects to return, the order in which to retrieve objects, SQL queries, and WHERE clauses. For methods that retrieve an ObjectCursor or ScrollableObjectCursor for all objects in persistent storage, you can set options such as the order in which to retrieve objects, SQL queries, and WHERE clauses If no data exists, the method returns the POFNotFound exception. All other error conditions will result in an exception according to the underlying persistent storage support. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 38 PersistentObject class methods The following methods are PersistentObject class methods. Therefore, all persistent objects in an application inherit these methods. findAll: Description Retrieves all objects from persistent storage as an ordered collection. findAllLimit: anInteger Description Retrieves the specified number of objects from persistent storage as an ordered collection. Parameter anInteger Specifies the maximum number of objects to be returned by this method. If you specify 0 or a negative number, the method returns an empty collection. If the specified number is greater than the number of objects in persistent storage, the method overwrites the specified size and returns a collection based on the size of the data. findAllOrderBy: aString Description Retrieves all objects from persistent storage as an ordered collection and returns them in the specified order. Parameter aString Specifies the order in which to sort the data before they are retrieved into the development environment. The string is in the format of an SQL order by clause using the column names found in the persistent store and the order (ASC for ascending and DESC for descending). For example, NAME ASC specifies to return the data in the NAME column in ascending order. Do not use the Smalltalk attribute names. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 39 findAllOrderBy: aString limit: anInteger Description Retrieves the specified objects from persistent storage as an ordered collection in the specified order. Parameters aString Specifies the order in which to sort the data before they are retrieved into the development environment. anInteger Specifies the maximum number of objects to be returned by this method. findQuery: aSQLString Description Retrieves the objects from persistent storage as an ordered collection based on the criteria of the SQL query. Parameter aSQLString Identifies the SQL query to be processed by the persistent store engine (typically, the database engine). The query specified must return data that can be unpacked as instances of the class on which the method was invoked. Use this method with caution because it is very specific to the underlying storage engine. This method does not work on abstract classes in the Relational POF. Using this method can reduce portability between different database systems, since the method can use and, thereby, expose database-specific features. If at all possible, avoid using this method. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 40 findQuery: aSQLString limit: anInteger Description Retrieves the objects from persistent storage as an ordered collection based on the criteria of the SQL query and the specified maximum number. Parameters aSQLString Identifies the SQL query to be processed by the persistent store engine. anInteger Specifies the maximum number of objects to be returned by this method. Use this method with caution because it is very specific to the underlying storage engine. This method does not work on abstract classes in the Relational POF. Using this method can reduce portability between different database systems, since the method can use and, thereby, expose database-specific features. If at all possible, avoid using this method. findWhere: aWhereString Description Retrieves the objects from persistent storage as an ordered collection based on the specified WHERE clause. Parameter aWhereString Specifies the WHERE clause to be processed by the persistent storage engine (typically, the database engine). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 41 findWhere: aWhereString limit: anInteger Description Retrieves the specified number of objects from persistent storage as an ordered collection based on the WHERE clause. Parameters aWhereString Identifies the WHERE clause to be processed by the persistent storage engine (typically, the database engine). anInteger Specifies the maximum number of objects to be returned by this method. findWhere: aWhereString orderBy: aString Description Retrieves objects from persistent storage as an ordered collection based on the WHERE clause and returns them in the specified order. Parameters aWhereString Identifies the WHERE clause to be processed by the persistent storage engine. aString Specifies the order in which to sort the data before they are retrieved into the development environment. findWhere: aWhereString orderBy: aString limit: anInteger Description Retrieves the specified number of objects from persistent storage as an ordered collection based on the WHERE clause and returns them in the specified order. Parameters aWhereString Identifies the WHERE clause to be processed by the persistent storage engine (typically, the database engine). aString Specifies the order in which to sort the data before they are retrieved into the development environment. anInteger Specifies the maximum number of objects to be returned by this method. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 42 openCursorAll Description Retrieves an ObjectCursor for all of the objects in persistent storage. openCursorAllOrderBy: aString Description Retrieves an ObjectCursor for all of the objects in persistent storage and returns them in the specified order. Parameter aString Specifies the order in which to sort the data before they are retrieved into the development environment. The string is in the format of an SQL order by clause using the column names found in the persistent store and the order (ASC for ascending and DESC for descending). For example, NAME ASC specifies to return the data in the NAME column in ascending order. Do not use the Smalltalk attribute names. openScrollableCursorAll Description Retrieves a ScrollableObjectCursor for all objects in persistent storage. openScrollableCursorAllOrderBy: aString Description Retrieves a ScrollableObjectCursor for all objects in persistent storage and returns them in the specified order. Parameter aString Specifies the order in which to sort the data before they are retrieved into the development environment. Cursors do not work on abstract classes in the Relational POF. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 43 openCursorQuery: aSQLString Description Retrieves an ObjectCursor for all objects in persistent storage based on the criteria of the SQL query. Parameter aSQLString Identifies the SQL query to be processed by the persistent store engine (typically, the database engine). The query specified must return data that can be unpacked as instances of the class on which the method was invoked. Use this method with caution because it is very specific to the underlying storage engine. Using this method can reduce portability between different database systems, since the method can use and, thereby, expose database-specific features. If at all possible, avoid using this method. openScrollableCursorQuery: aSQLString Description Retrieves a ScrollableObjectCursor for all objects in persistent storage based on the criteria of the SQL query. Parameter aSQLString Identifies the SQL query to be processed by the persistent store engine (typically, the database engine). Use this method with caution because it is very specific to the underlying storage engine. Using this method can reduce portability between different database systems, since the method can use and, thereby, expose database-specific features. If at all possible, avoid using this method. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 44 openCursorWhere: aWhereString Description Retrieves an ObjectCursor for all objects in persistent storage based on the specified WHERE clause. Parameter aWhereString Specifies the WHERE clause to be processed by the persistent storage engine (typically, the database engine). Cursors do not work on abstract classes in the Relational POF. openCursorWhere: aWhereString limit: anInteger Description Retrieves an ObjectCursor for the specified number of objects in persistent storage based on the WHERE clause. Parameters aWhereString Identifies the WHERE clause to be processed by the persistent storage engine (typically, the database engine). anInteger Specifies the maximum number of objects to be returned by this method. openScrollableCursorWhere: aWhereString Description Retrieves a ScrollableObjectCursor for all objects in persistent storage based on the specified WHERE clause. Parameter aWhereString Specifies the WHERE clause to be processed by the persistent storage engine (typically, the database engine). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 45 openScrollableCursorWhere: aWhereString limit: anInteger Description Retrieves a ScrollableObjectCursor for the specified number of objects in persistent storage based on the WHERE clause. Parameters aWhereString Identifies the WHERE clause to be processed by the persistent storage engine (typically, the database engine). anInteger Specifies the maximum number of objects to be returned by this method. Cursors do not work on abstract classes in the Relational POF. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 46 Examples Following are examples of some of the object-retrieval services. Returning ordered collections Below are some examples of returning ordered collections. ♦ The following example specifies to return four records from the Commercial table where output from the query is sorted in ascending order by custName: Corporate findAllOrderBy: 'custName ASC' limit: 4 ♦ The following example specifies to return the first four records from the Commercial table where the custID is greater than “3–0499”: Corporate findQuery: 'SELECT * FROM Commercial WHERE custID>"3-0499"' limit: 4 ♦ The following example specifies to return the first four records from the Commercial table where output from the query is sorted in ascending order by custName where the custID is greater than “3–0499”: Corporate findWhere: 'custID>"3-0499"' orderBy: 'custName ASC' limit: 4 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 47 Returning object cursors or scrollable object cursors Below are examples of returning object cursors or scrollable object cursors. ♦ The following example opens an ObjectCursor for all records from the Commercial table where output from the query is sorted in ascending order by custName: Corporate openCursorAllOrderBy: 'custName ASC' ♦ The following example opens a ScrollableObjectCursor for all records from the Commercial table where output from the query is sorted in ascending order by custName: Corporate openScrollableCursorAllOrderBy: 'custName ASC' ♦ The following example opens an ObjectCursor for all records from the Commercial table where the custID is greater than “3–0499”: Corporate openCursorQuery: 'SELECT * FROM Commercial WHERE custID>"3-0499"' ♦ The following example opens a ScrollableObjectCursor for all records from the Commercial table where custID is greater than “3–0499”: Corporate openScrollableCursorQuery: 'SELECT * FROM Commercial WHERE custID>"3-0499"' ♦ The following example opens an ObjectCursor for all records from the Commercial table where output from the query is sorted in ascending order by custName where custID is greater than “3–0499”: Corporate openCursorWhere: 'custID>"3-0499"' orderBy: 'custName ASC' ♦ The following example opens a ScrollableObjectCursor for all records from the Commercial table where output from the query is sorted in ascending order by custName where custID is greater than “3–0499”: Corporate openScrollableCursorWhere: 'custID>"3-0499"' orderBy: 'custName ASC' Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object-retrieval services 48 Template-retrieval services Use the template-retrieval services to return objects from persistent storage that match the values of an object that you specify. You can retrieve the data in ordered collections or cursors. For methods that retrieve objects from persistent storage as an ordered collection, you can set options such as a limit on how many objects to return and the order in which to retrieve objects. The POF automatically creates a WHERE clause for the primitive attributes with values that differ for nil. It combines all of the conditions with ANDs. For methods that retrieve an ObjectCursor or ScrollableObjectCursor for objects in persistent storage, you can set only the order in which to retrieve objects. If no data exists, the method returns the POFNotFound exception. All other error conditions result in an exception according to the underlying persistent storage support. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Template-retrieval services 49 PersistentObject instance methods The following methods are PersistentObject instance methods. Therefore, all persistent objects in an application inherit these methods. find Description Retrieves all objects from persistent storage that match the specified object values. findLimit: anInteger Description Retrieves the specified number of objects from persistent storage that match the specified object values. Parameter anInteger Specifies the maximum number of objects to be returned by this method. If you specify 0 or a negative number, the method returns an empty collection. If the specified number is greater than the number of objects in persistent storage, the method overwrites the specified size and returns a collection based on the size of the data. findOrderBy: aString Description Retrieves all of the objects from persistent storage that match the specified object values and returns them in the specified order. Parameter aString Specifies the order in which to sort the data before it is retrieved into the development environment. The string is in the format of an SQL order by clause using the column names found in the persistent store and the order (ASC for ascending and DESC for descending). For example, NAME ASC specifies to return the data in the NAME column in ascending order. Do not use the Smalltalk attribute names. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Template-retrieval services 50 findOrderBy: aString limit: anInteger Description Retrieves the specified number of objects from persistent storage that match the specified object values in the specified order. Parameters aString Specifies the order in which to sort the data before they are retrieved into the development environment. anInteger Specifies the maximum number of records to be returned by this method. openCursor Description Retrieves an ObjectCursor for all objects in persistent storage that match the specified object values. openCursorOrderBy: aString Description Retrieves an ObjectCursor for all objects in persistent storage that match the specified object values and returns them in the specified order. Parameter aString Specifies the order in which to sort the data before they are retrieved into the development environment. The string is in the format of an SQL order by clause using the column names found in persistent storage and the order (ASC for ascending and DESC for descending). For example, NAME ASC specifies to return the data in the NAME column in ascending order. Do not use the Smalltalk attribute names. openScrollableCursor Description Retrieves a ScrollableObjectCursor for all objects in persistent storage that match the specified object values. Cursors do not work on abstract classes in the Relational POF. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Template-retrieval services 51 openScrollableCursorOrderBy: aString Description Retrieves a ScrollableObjectCursor for all objects in persistent storage that match the specified object values and returns them in the specified order. Parameter aString Specifies the order in which to sort the data before they are retrieved into the development environment. Cursors do not work on abstract classes in the Relational POF. Examples Following are examples of some of the template-retrieval services. Returning ordered collections The following example returns the first two records from the LineItem table where output from the query is sorted in ascending order by lineNumber that has the value specified in the aLineItem object: aLineItem := LineItem template. aLineItem lineNumber: 1. aLineItem findAllOrderBy: 'lineNumber ASC' limit: 2 Returning object cursors or scrollable object cursors Below are examples of returning object cursors or scrollable object cursors. ♦ The following example opens an ObjectCursor for all records that match the aLineItem object value from the LineItem table in ascending order by lineNumber: aLineItem := LineItem template. aLineItem lineNumber: 1. aLineItem openCursorOrderBy: 'lineNumber ASC' ♦ The following example opens a ScrollableObjectCursor for all records that match the aLineItem object value from the LineItem table in ascending order by lineNumber: aLineItem := LineItem template. aLineItem lineNumber: 1. aLineItem openScrollableCursorOrderBy: 'lineNumber ASC'. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Template-retrieval services 52 Persistency services Use the persistency services to manipulate objects. The POF automatically issues a begin transaction before performing any action against the persistent store. The POF issues a commit or rollback depending on the result. If an error occurs with the method execution, the method returns an exception. When the save methods execute, the POF automatically determines whether the action is an insert or an update. There are three categories of persistency services: ♦ Storage. Delete, refresh, or save objects. ♦ Transformation. Affect preprocessing and postprocessing. The POF sends these messages to objects. ♦ Verification. Verify persistency. They return TRUE for all objects for a successful verification; otherwise, they return FALSE. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Persistency services 53 PersistentObject instance methods The following methods are PersistentObject instance methods. Therefore, all persistent objects in an application inherit these methods. delete Description Deletes the object from persistent storage. The PID is used internally to identify the object. refresh Description Refreshes the object from persistent storage, including the primitive, associated, and aggregated attributes. save Description Saves the object into persistent storage, including all of the object’s attributes. saveAll Description Saves the object and all of its referenced objects (associated and aggregated) into persistent storage, including all of the objects’ attributes. saveComposite Description Saves the object and its aggregated referenced objects into persistent storage. It stores all of the object’s attributes. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Persistency services 54 savePrimitiveAttributes Description Saves the object and its primitive attributes into persistent storage. saveAssociationAttributes Description Saves the object and its attributes that represent associated objects into persistent storage. saveAggregationAttributes Description Saves the object and its attributes that represent aggregated objects into persistent storage. postDelete Description Arrives at an object immediately after a delete operation has been performed in the persistent store. The transaction is still active. It can be used to implement housekeeping tasks or simply to do postprocessing of the object. postInsert Description Arrives at an object immediately after an insert operation has been performed in the persistent store. The transaction is still active. It can be used to implement housekeeping tasks or simply to do postprocessing of the object. postObjectCreate Description Arrives at an object immediately after the object has been created (typically in a find operation). It can be used to implement housekeeping tasks or simply to do postprocessing of the object. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Persistency services 55 postUpdate Description Arrives at an object immediately after the update operation has been performed in the persistent store. The transaction is still active. It can be used to implement housekeeping tasks or simply to do postprocessing of the object. preDelete Description Arrives at an object immediately before the delete operation is performed in the persistent store. The transaction is still active. It can be used to implement housekeeping tasks or simply to do preprocessing of the object. preInsert Description Arrives at an object immediately before the insert operation is performed in the persistent store. The transaction is still active. It can be used to implement housekeeping tasks or simply to do preprocessing of the object. preObjectCreate Description Arrives at an object before the object is created and all of the attributes receive data (typically in a find operation). It can be used to implement housekeeping tasks or simply to do preprocessing of the object. preUpdate Description Arrives at an object before the update operation is performed in the persistent storage. The transaction is still active. It can be used to implement housekeeping tasks or simply to do preprocessing of the object. isPersistent Description Returns TRUE if the object has a matching object in persistent storage (for example, objects retrieved with find or open, or new objects that have been saved in the database). isPersistentObject Description Returns TRUE for all objects that inherit from PersistentObject. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Persistency services 56 Examples The following examples demonstrate Storage services: ♦ This example deletes the object from persistent storage: aLineItem := LineItem findAll first. aLineItem delete. ♦ This example saves the aLineItem object: aLineItem := LineItem findAll first. aLineItem quantity: 100. aLineItem save. ♦ This example saves the aggregate attributes for the aLineItem object: aLineItem := LineItem findAll first. aLineItem saveAggregationAttributes. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Persistency services 57 Object cursor services The POF ObjectCursor basically works as a typical database cursor. The main difference is that it returns real Smalltalk objects, such as the different find methods. ObjectCursor can move only forward in a result set. For moving backward and positioning functionality, use ScrollableObjectCursor. Be aware of cursor stability issues on different persistent storage engines. ObjectCursor instance methods The following methods are ObjectCursor instance methods. Therefore, all object cursors in an application inherit these methods. close Description Closes the cursor. If the cursor is already closed, nothing happens. current Description Returns the current object in the context of the cursor. This object is an instance of a subclass of PersistentObject. If the cursor is closed, the method generates an exception. isObjectCursor Description Returns TRUE from all instances of ObjectCursor or FALSE if the cursor is not an instance of ObjectCursor. isOpen Description Identifies the status of the cursor by returning TRUE if it is open or FALSE if it is closed. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object cursor services 58 next Description Positions the cursor at the next object for the cursor in persistent storage and returns it if the object is an instance of a subclass of PersistentObject. If the object is not an instance of a subclass of PersistentObject, the method returns nil. If no data exists, it generates a POFNotFound exception. All other error conditions result in an exception according to the underlying persistent storage support. open Description Opens the cursor and positions it before the first object. A successive ObjectCursor>>next will fetch the first object for the cursor. If no data exists, it generates a POFNotFound exception. All other error conditions will result in an exception according to the underlying persistent storage support. position Description Returns the current cursor position in integer format. Example ObjectCursor instance method The following example opens an object cursor: anObjectCursor open Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object cursor services 59 Scrollable object cursor services Use the ScrollableObjectCursor to randomly access large sets of data without having to store all of the data in memory at a time. This class is expected to be a subclass of ObjectCursor and inherits ObjectCursor methods. If no data exists, it generates a POFNotFound exception. All other error conditions result in an exception according to the underlying persistent storage support. ScrollableObjectCursor instance methods The following methods are ScrollableObjectCursor instance methods. Therefore, all scrollable object cursors in an application inherit these methods. first Description Positions the cursor at the first object for the cursor in persistent storage and returns an instance of a subclass of PersistentObject or nil. last Description Positions the cursor at the last object for the cursor in persistent storage and returns an instance of a subclass of PersistentObject or nil. isScrollableObjectCursor Description Returns TRUE from all instances of ScrollableObjectCursor if the cursor is an instance of ScrollableObjectCursor. If the cursor is not an instance of ScrollableObjectCursor, it returns FALSE. previous Description Positions the cursor at the previous object for the cursor in persistent storage and returns an instance of a subclass of PersistentObject or nil. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Scrollable object cursor services 60 setPositionTo: anInteger Description Sets the current cursor position and returns an instance of a subclass of PersistentObject or nil. Parameter anInteger Specifies an integer indicating to which element to go. size Description Returns the size of the result set represented by the cursor. If the cursor is closed, the method generates an exception. Example ScrollableObjectCursor instance method The following sets the position of a scrollable object cursor to 11: aScrollableObjectCursor setPositionTo: 11 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Scrollable object cursor services 61 Transaction manager services The transaction manager uses the following instance variables and methods. Transaction manager instance variable The instance variable transactionLevel indicates the current transaction level. Initial value is 0 (zero). Transaction manager instance methods begin Description Starts a transaction and increments the transaction level. Internally, the POF might issue a commit or rollback against persistent storage to clear all current actions if the transaction level is 0 (zero). If the transaction level is greater than 0, the method creates a savepoint. commit Description Commits a transaction and decrements the transaction level if it is greater than 0 (zero). Internally, the POF issues a commit against persistent storage to commit all current actions if the transaction level is 0. If the transaction level is greater than 1, nothing happens. rollback Description Rolls back a transaction and decrements the transaction level if it is greater than 0 (zero). Internally, the POF issues a rollback against persistent storage to roll back all current actions if the transaction level is 0. If the transaction level is greater than 1, a rollback to savepoint is issued against persistent storage to roll back to the last savepoint. Example TransactionManager instance method The following example rolls back a transaction: aTransactionManager rollback Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Transaction manager services 62 Object pool services The PersistentObjectPool class uses the following instance methods: disable Description Disables the object pool. The POF will not try to maintain integrity within the image. enable Description Enables the object pool. The POF will maintain integrity within the image while the pool is enabled. flush Description Flushes all objects of all classes from the object pool. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object pool services 63 flushForClass: aClass Description Flushes all objects of the specified class from the object pool. Parameter aClass Specifies the name of the class. flushForObject: anObject Description Flushes the specified object from the pool. Parameter anObject Specifies the name of the object. initializeInstanceVariables Description Initializes the instance variables for the class. isActive Description Returns TRUE if the pool is active or FALSE if the pool is not active. isActive: aBoolean Description Specifies the active state of the pool. The pool is completely emptied if the state is set to FALSE. Parameter aBoolean Value can be TRUE or FALSE. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Usage protocol Section: Object pool services 64 4 Framework internals Introduction This section explains the internal operations of the framework, such as how the request brokers for the Abstract framework and its extensions process a request, how the transaction manager functions, and how proxy objects work. Persistency Request Broker The Persistency Request Broker manages requests between application objects and persistent storage. When an application issues a find, save, or delete request for an object, the Persistency Request Broker uses the PersistentBrokerManager to get information on which broker can satisfy the request. It then forwards the request to the broker. The Abstract framework’s PersistencyRequestBroker handles all of the requests that enter the framework. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Introduction 65 The following figure shows the sequence of events that occurs when an application issues a request: PersistentObject sends find request n aCustomer PersistencyRequestBrokerControl requests ID of appropriate broker o p sends broker instance PersistencyBrokerManagerControl sends find request q aPersistencyBroker The following steps correspond to the figure numbers: 1. The object (a subclass of PersistentObject) issues a request to the PersistencyRequestBroker. 2. PersistencyRequestBroker asks the PersistencyBrokerManager how to perform the task. PersistencyBrokerManager has a dictionary that identifies the responsibilities for each class, what tasks each class can perform, and each class’s associated brokers. 3. PersistencyBrokerManager identifies the class to perform the request and sends this information back to the PersistencyRequestBroker. 4. PersistencyRequestBroker passes the request on to the instance of the subclass of the PersistencyBroker that is responsible for the task. (This instance is the same instance that was returned in step 3.) Which class is responsible depends upon which framework extension you are using and how it is configured. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Persistency Request Broker 66 Persistency brokers There are different types of persistency brokers depending upon which framework extension you are using: the Relational POF or the UniSQL POF. The class hierarchy is PersistencyBroker with subclasses DynamicPersistencyBroker and MFBroker, where the dynamic behaves differently in relation to the PersistencyBrokerManager. Relational POF broker After the Abstract framework request broker identifies that the relational broker should perform the request, the POF passes the request to the Relational POF brokers. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Persistency brokers 67 The following figure shows how the Relational POF brokers handle the request: PersistencyRequestBrokerControl sends find request n sends SQL statements MFBroker o finds classes r Relational Database s sends data t transforms data requests SQL statements p q sends SQL statements MFStatementGeneratorControl The following steps correspond to the figure numbers: 1. The PersistencyBroker passes the request to the MFBroker instance. (This step corresponds to step 4 in the previous section that discusses the “Persistency Request Broker,” beginning on page 32.) 2. MFBroker finds the MFClasses that will be involved in the request. 3. MFBroker asks the MFStatementGenerator to generate the necessary SQL statements. 4. MFStatementGenerator generates the SQL statements; then it sends the statements back to MFBroker. 5. MFBroker passes the statements to the database. 6. The database returns the requested data to MFBroker. 7. MFBroker transforms the resulting table/row/messages into a proper response. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Persistency brokers 68 UniSQL POF broker After the Abstract framework request broker identifies that the dynamic broker should perform the request, the POF passes the request to the UniSQL POF brokers. The following figure shows how the UniSQL POF brokers handle the request: PersistencyRequestBrokerControl sends find request n sends map info UFBroker requests map info o q UniSQL API p sends map info SmalltalkToDatabaseMaps The following steps correspond to the figure numbers: 1. The PersistencyBroker passes the request to UFBroker. 2. UFBroker asks the SmalltalkToDatabaseMaps class for mapping information. 3. The SmalltalkToDatabaseMaps class returns the mapping information to UFBroker. 4. UFBroker uses the information from the maps to process the request directly against the database API. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Persistency brokers 69 Transaction manager Transaction managers are classes that synchronize multiple transactions so that they occur at the same time. The POF TransactionManager class handles all of the transactions for the Abstract framework and both extensions. To initiate a transaction request in TransactionManager, the request must start with a begin method: TransactionManager begin. aCustomer save. anotherCustomer delete. TransactionManager commit. A commit or rollback method indicates the end of the transaction. The transaction manager automatically forwards any request it receives to all of the registered persistent stores. When a persistent store processes the commit method, the transaction is written to persistent storage—this is called the commit point. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Transaction manager 70 POF and transactions The POF automatically issues a begin and a commit or rollback for all save and delete operations, so you do not have to handle the transaction manually. To delete an object, enter the following code: aCustomer delete In this example, the following communication with the database takes place: COMMIT; DELETE FROM customer WHERE customerid = 100; COMMIT; You should consider transaction management if the application call is for multiple persistent storage interactions. Then you can start grouping transactions. The following example shows the previous code executing multiple interactions: TransactionManager begin. aCustomer save. anotherCustomer delete. TransactionManager commit. The previous example generates the following code: COMMIT; INSERT INTO customer (customerid, name) VALUES 101, 'Fini Thomsen'; DELETE FROM customer WHERE customerid = 100; COMMIT; Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Transaction manager 71 Errors If you decide that a transaction should not take place, you can issue a rollback to the transaction manager instead of the commit. Remember that begin and commit or rollback statements always must be paired. Multiple transactions You can process multiple transactions with a single request by nesting transaction requests. TransactionManager assigns reference numbers to the transactions. For example, when TransactionManager has no transaction request, the status number is zero. When it encounters the first begin method, it increments the counter to one. If this transaction is the only one processed, when it reaches the commit method and completes the transaction, it resets the number to zero. The following table illustrates how the TransactionManager counter increments and decrements the transaction level when executing a single line of Smalltalk code: Smalltalk TL Database 0 aCustomer delete 1 COMMIT; 1 DELETE FROM customer WHERE customerid = 100; 0 COMMIT; However, if there is another transaction nested within the transaction, TransactionManager assigns it the number two when it reads the begin method. Only after TransactionManager completes processing the second transaction does it return to processing the first transaction. It then completes the first transaction and resets the counter to zero when processing the final commit. The following table illustrates how the TransactionManager counter increments and decrements the transaction level when executing nested transactions: Smalltalk TL Database 0 TransactionManager begin 1 COMMIT; aCustomer delete 2 DELETE FROM customer WHERE customerid = 100; 1 anotherCustomer save 2 INSERT INTO customer WHERE customerid = 200; 1 TransactionManager commit Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Transaction manager 0 COMMIT; 72 Using proxies Proxy basics In an access layer, it is necessary to provide a mechanism that lets developers continue to think in terms of objects without sacrificing performance or adding complexity. It is important to realize that objects are not data. An access layer can provide only an object view of data by packaging it in a manner that makes it appear as objects to an application developer. This packaging introduces structure into otherwise unstructured data, and any successful object-data integration must hide this packaging from the developer. Proxy objects A proxy object represents a real object that has not yet been retrieved from persistent storage. It is a placeholder for the real object and contains just enough information to retrieve the real object when needed. A proxy object contains: ♦ Type or class of object to be retrieved ♦ Primary keys and their values for the tables that the object may span Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Using proxies 73 Proxy object behavior A proxy object is not intended to be exposed to the developer and turns into a real object without developer intervention. For example, a developer may retrieve an Employee object that contains a Company object. However, to optimize performance, the developer or access layer chooses to proxy the Company instead of retrieving it with the Employee. The developer does not have to be aware that the Company has not been retrieved from the database and is only a proxy object at the application level. When the developer sends a message to this proxy object, such as by asking the Company for its name, the proxy comes to life. Upon receiving a request, a proxy object: 1. Traps the request. 2. Uses information stored in the proxy to retrieve the original object or objects from persistent storage. 3. Transforms the proxy object into the real object. 4. Reissues the trapped request so the correct action is performed. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Using proxies 74 Proxy implementation The POF differentiates between single proxy objects and collection proxy objects. It provides the MFProxy class and a specialization, MFCollectionProxy, as shown in the following figure: MFProxy MFCollectionProxy MFSingleProxy For the UniSQL framework, the classes start with UF, not MF. For example, instead of MFProxy, the UniSQL framework uses UFProxy. The MFSingleProxy object represents a single instance of an object in persistent storage. A MFCollectionProxy object represents a collection of zero or more objects in persistent storage. MFCollectionProxy objects are placeholders for a collection such as an array, linked list, or some other data structure used to contain collections of objects. A collection proxy knows the type of collection it represents. It also has behavior that knows how to retrieve a collection instead of a single instance of an object. In the Relational POF, a new type Proxy has been added for dependent objects, MFRowProxy. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Using proxies 75 Implementing proxies Implementing a proxy is easier in, but not restricted to, a dynamically bound language, such as Smalltalk. The process involves: 1. Trapping the request. 2. Retrieving objects. 3. Transforming a proxy into a real object. 4. Reissuing the request. Trapping requests In Smalltalk, the Object class provides the following method, which is called whenever a message is sent to an object for which it does not know how to respond: doesNotUnderstand: selector args: args. A simple approach to trapping a request in a proxy is to overload the doesNotUnderstand: args: method with one that handles the request and performs each of the four steps. Typically, no other public methods get sent to the MFProxy; often private methods are required to prevent potential collisions with methods to which the real object might respond. Also, often you must overload methods inherited from Object, such as class and print. Use caution in overloading the doesNotUnderstand: args: method. For example, when the name is requested of the Company object of an Employee, the instance of a MFProxy object does not have a method called name and therefore calls the doesNotUnderstand: args: method. However, instead of the message being delegated up to Object where it is implemented, ObjectStudio calls the overloaded method, which retrieves the real object, transforms the proxy into this real object, and then reissues the request (for example, name) to the real object so the proper return value is received by the sender. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Using proxies 76 Retrieving objects Once the request has been trapped, the proxy object must retrieve the real object or the collection of objects. For a relational database, this retrieval translates into: 1. Constructing one or more SQL statements to retrieve the data representing the object or objects 2. Issuing these requests 3. Transforming the data into objects The POF architecture handles these steps by making the proxy object delegate this request to the access layer. Transforming a proxy into a real object Once the real object or objects have been retrieved, the POF must transform the proxy into the real object using one of the following approaches: ♦ Destructive transformation ♦ Nondestructive transformation Destructive transformation. The destructive approach is easiest but, typically, is an option only in a language such as Smalltalk. The Mapping Tool uses this approach. Destructive transformation involves replacing an instance of the proxy with an instance of another object as in the following examples: self becomeOneWith: realObject or realObject become: self The #becomeOneWith: or #become: method of Object is used and self represents the instance of the proxy. The primary issue in using the destructive approach is that operations such as #becomeOneWith: are inefficient operations in Smalltalk environments and impede system performance. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Using proxies 77 Nondestructive transformation. Nondestructive transformation involves setting the attribute of the object that references the proxy to the real object or collection of real objects. Nondestructive transformation requires the proxy to contain additional information, such as the parent object and the parent attribute. Consider the following when using the nondestructive approach: ♦ Any architecture implementing nondestructive transformation must also handle object integrity. If it does not handle integrity, the architecture would allow more than one instance of the same persistent object to exist at the application level. ♦ All references to the proxy object, such as dependencies, now reference the real object. These references do not occur automatically with the nondestructive approach. ♦ Sometimes messages can be lost by the nondestructive approach to transforming a proxy (for example, if a proxy is encountered within a loop). Because of these issues, the Mapping Tool uses a destructive approach to transforming proxies. Reissuing requests Once the proxy has been transformed into the real object or objects, the original request (for example, company name) is reissued to the real objects. It is reissued so that the application continues to execute seamlessly without knowledge of the proxy transformation. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Using proxies 78 Object pool The access layer of an application provides an object view of data by replicating objects at the application level. Because these objects are further away from their persistent store, there is a greater chance of compromising integrity. To ensure integrity, the POF checks objects for uniqueness when it retrieves them from the database. Every time an object is instantiated, the POF first checks the object pool for the object’s existence. The object pool caches the objects for the POF. If an object already exists in the pool, then the POF uses the existing object and updates its data depending on the integrity option specified in the broker. If the object being instantiated does not exist, the POF adds it to the pool. The following figure illustrates how the POF object pool uses dictionaries to locate objects: Dictionary2 Key Value objectID aCustomer ... Dictionary1 ... Key Value classname classname Dictionary3 .classname .. Key objectID Value aContact ... ... Keys Class Names Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Object pool Values IdentityDictionaries (Keys = obj id, Values = objects) 79 The POF implements object integrity using the class PersistentObjectPool. PersistentObjectPool provides the basic infrastructure for implementing object pools and ensuring object integrity. PersistentObjectPool is a singleton class. As the application continues to retrieve more objects, the application pool expands and consumes more memory. Although PersistentObjectPool provides the mechanism to flush or clean the pool, you should not have to use this mechanism very often because it uses weak dictionaries that automatically have garbage collected regularly. Object integrity provides the following benefits: ♦ Ensures that only one instance of an object exists in an application ♦ Updates primitive and nonprimitive attributes of this object whenever more current data is encountered in the database depending on the integrity options specified Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Framework internals Section: Object pool 80 5 Benchmarking Benchmarking application The POF includes a benchmarking loadable application called Benchmarking framework. This application provides an interface that allows you to track each chunk of code (the code between BenchmarkClass>>begin: and BenchmarkClass>>end statements) as it executes. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmarking application 81 Initiating benchmarking You can initiate benchmarking by loading an application such as the Mapping Tool or by loading the Benchmarking framework directly. Loading and accessing the Benchmarking framework Because the Benchmarking framework is a loadable application, you must load it into ObjectStudio before you can access it. Load the Benchmarking framework: 1. Load the Modeling Base application. This application contains some classes that the Benchmarking framework needs. 2. Load the Benchmarking application. 3. Double-click the Benchmarking icon on the ObjectStudio desktop to start the Benchmark Explorer. The Benchmark Explorer appears as shown: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmarking application 82 Using the Benchmarking framework You can call the Benchmarking framework from: ♦ Your code. Embed the BenchmarkClass>>begin: and BenchmarkClass>>end statements in your application. ♦ Workspace. Run code, including the Benchmark begin and Benchmark end statements, in the workspace. The following figure shows an example of code that calls the Benchmarking framework: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmarking application 83 Activating benchmarking To activate benchmarking using the Benchmark Explorer, click Activate. As ObjectStudio executes the code, the Benchmark Explorer displays the benchmark data or observation for each chunk of code (which can be very time-consuming) if Automatic is checked. The following figure shows the Benchmark Explorer with benchmark statistics: Notice that you can capture nested observations. To disable the automatic update, uncheck the Automatic check box. Deactivating benchmarking To deactivate benchmarking, click Deactivate. Resetting benchmarking Resetting the Benchmark Explorer means that you clear all observations currently captured by the Explorer. To reset the Benchmarking application, click Reset. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmarking application 84 Refreshing the benchmarking data You can refresh the benchmarking data in two ways: ♦ Check the Automatic check box to automatically display every observation as the code executes. ♦ Click Refresh to update the current display. Do not check the Automatic check box if you call the Benchmarking framework from large applications; the Benchmark Explorer displays observations of itself and will use extra time and resources to update the display. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmarking application 85 Benchmark class The Benchmark class can be used to add benchmarking features to an application. It supports embedded observations that allow you to perform benchmarking at multiple levels within an application. Benchmark is a subclass of the Object class. The POF includes support for benchmarking by default. The Benchmark class comes with the BenchmarkExplorerController that displays the benchmark interface. Benchmark is a class-based singleton. Therefore, all communication to it should be done through the class methods provided. Benchmark class methods activate Description Activates benchmarking. addArrayOfData: anArray Description Adds an array of data to the current benchmark object. There must be an active benchmark. Parameter anArray Specifies an array of data. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmark class 86 addData: anObject Description Adds data to the current benchmark object. There must be an active benchmark. Parameter anObject Identifies any data that you want to associate with an observation. begin: aDescription Description Begins a new benchmark observation. The new object will be embedded as a subobservation within the active object if one exists. Parameter aDescription Specifies the information you want to display in the Explorer. This method must be paired with the BenchmarkClass>>end method. begin: aDescription with: anObject Description Begins a new benchmark observation. The new object will be embedded as a subobservation within the active object if one exists. Parameters aDescription Specifies the information you want to display in the Explorer. anObject Identifies any data that you want to associate with an observation. This method must be paired with the BenchmarkClass>>end method. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmark class 87 begin: aDescription with: anObject with: object2 Description Functions like #begin:with: allow you to specify multiple objects of data to be added to the data associated with the observation. This method must be paired with the BenchmarkClass>>end method. begin: aDescription with: anObject with: object2 with: object3 Description Functions like #begin:with: allow you to specify multiple objects of data to be added to the data associated with the observation. This method must be paired with the BenchmarkClass>>end method. begin: aDescription with: anObject with: object2 with: object3 with: object4 Description Functions like #begin:with: allow you to specify multiple objects of data to be added to the data associated with the observation. This method must be paired with the BenchmarkClass>>end method. deactivate Description Deactivates benchmarking. end Description Ends the active benchmark object. endWith: anObject Description Ends the active benchmark object. Parameter anObject Identifies any data that you want to associate with an observation. endWith: anObject with: object2 Description Functions like #endWith: allow you to specify multiple objects of data to be added to the data associated with the observation. endWith: anObject with: object2 with: object3 Description Functions like #endWith: allow you to specify multiple objects of data to be added to the data associated with the observation. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmark class 88 isActive Description Returns TRUE if benchmarking is active and FALSE if it is not. isActive: aBoolean Description Sets the active status of benchmarking. observations Description Returns a collection of all observations captured by benchmarking since the last BenchmarkClass>>reset. The return value is an array. reset Description Clears observations and the active benchmark object. time Description Calculates the time spent between the first and the last observation and returns a string containing the time spent in the format HH:MM:SS.HH. If the last observation is not complete or if no observation exists, the text is N/A. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmark class 89 Examples These examples illustrate the Benchmark class: ♦ The following example stores an array of objects for the active benchmark: Benchmark begin: 'My observation'. Benchmark addArrayOfData: anArray. <action> Benchmark end. ♦ The following example stores an object for the active benchmark object: Benchmark begin: 'My observation'. Benchmark addData: anObject. <action> Benchmark end. ♦ The following example captures the time it takes to perform an action: Benchmark begin: 'My observation'. <action> Benchmark end. ♦ The following example captures the time it takes to perform an action within an action: Benchmark <action1> Benchmark <action2> Benchmark Benchmark ♦ begin: 'My observation'. begin: 'My sub-observation'. end. end. The following example captures the time it takes to perform an action and store a value with it: Benchmark begin: 'My observation' with: value. <action> Benchmark end. ♦ The following example captures the time it takes to perform an action and store multiple values with it: Benchmark begin: 'My observation' with: value1 with: value2 with: value3 with: value4. <action> Benchmark end. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Benchmarking Section: Benchmark class 90 6 Introduction to the Relational POF The Relational POF The Relational POF provides tools for defining how objects in an application map to the tables in a database. The Relational POF handles the mechanics of storing and retrieving data from the relational database and providing data to the ObjectStudio application in object form. These features allow you to concentrate on objects, without considering the details of the relational database implementation. The Relational POF consists of an extension to the POF Abstract framework (standard abstraction classes) and the ObjectStudio Mapping Tool interface. The Mapping tool cannot be used with the repository-based version of ObjectStudio; it is only available with the file-based version. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Relational POF 91 FrameWork extension The framework extension handles the interaction between the Abstract framework and the relational database. The following figure shows the classes in the framework and their interactions: PersistentObject PersistencyRequestBroker PersistencyBrokerManager ObjectCursor PersistencyBroker MFBroker ScrollableObjectCursor TransactionManager Mapping Tool interface The Mapping Tool interface automates the process of finding, saving, and deleting objects in a relational database. It allows you to define how objects in an application map to the tables in the database. It also allows you to convert relational data into objects by assembling the attributes in the ObjectStudio development environment. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Relational POF 92 The Mapping Tool interface This section describes how to install and uninstall the ObjectStudio Mapping Tool and how to use it. Read the readme.txt file for the latest information that may not have made it into this manual. Installation requirements To install the Mapping Tool, your system must meet the following requirements: ♦ An IBM PC or compatible 486 or higher ♦ Microsoft Windows NT® Version 3.51 or higher, or Windows 95 ♦ ObjectStudio 6.0 installed ♦ ObjectStudio Modeling Tool 6.0 installed (the Mapping Tool uses some of the Modeling Tool files) ♦ Minimum of 4 MB RAM available after installing ObjectStudio and the Modeling Tool ♦ Minimum of 3.5 MB available disk space after installing ObjectStudio and the Modeling Tool For best results, do not use other applications on your computer while you are running the installation procedure. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 93 Installing the Mapping Tool To install the Mapping Tool: 1. If installing from a CD-ROM or network, navigate to the appropriate directory and run setup.exe. If installing from diskette, insert Disk 1 into drive A or B and run setup.exe from the diskette. 2. Provide the information requested by the install wizard. You should install the Mapping Tool into the same directory as the Modeling Tool. 3. After the installation is complete, start ObjectStudio. 4. Load the Mapping Tool application from the Load Application dialog box. 5. Start the Mapping Tool by double-clicking the Mapping Tool icon on the ObjectStudio desktop. 6. (Optional) Create an image file with the Mapping Tool loaded by selecting File ⇒ Save image from the ObjectStudio desktop menu, specifying the directory and file name, and then saving the image. You must always have a copy of the default image file (–iostudio.img). Either do not overwrite it, or back it up in another directory before you overwrite it. 7. If you created an image with the Mapping Tool loaded, edit the ObjectStudio icon: ♦ For Windows 95, select the ObjectStudio shortcut with mouse button 2 and then select Properties from the icon pop-up menu. Select the Shortcut tab; then in the Target field, change the -iostudio.img parameter to the name of the new image file. Click OK. ♦ For Windows NT, select the ObjectStudio icon with mouse button 2; then select File Properties. In the Command Line field, change the -iostudio.img parameter to the name of the new image file. Click OK. When you double-click the ObjectStudio icon, ObjectStudio starts and loads the Mapping Tool into the image. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 94 Uninstalling the Mapping Tool This section describes how to remove the Mapping Tool from your system. The uninstall program does not remove folders or files that were not created by the setup program. Windows 95 To uninstall the Mapping Tool on Windows 95, perform the following: 1. Select Start ⇒ Settings ⇒ Control Panel ⇒ Add/Remove Program. 2. Select ObjectStudio Mapping Tool from the entry field and click Add/Remove. 3. Click Yes to confirm that you want to remove the Mapping Tool from your system. The uninstall program removes the Mapping Tool files. 4. Click OK when the uninstall program finishes removing the files. 5. Click OK to close the Add/Remove Programs Properties dialog box. Windows NT To uninstall the Mapping Tool on Windows NT, double-click the Uninstall icon in the folder that contains the Mapping Tool icons. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 95 Starting the Mapping Tool Before you can start the ObjectStudio Mapping Tool, you must: 1. Create the classes and tables you want to map. 2. Prepare the classes and tables you want to map. 3. Load database support for the database server you are using and log in to the database. 4. Load the Modeling Tool and Mapping Tool. 5. (Optional) Save an image with the Mapping Tool loaded. 6. Load the classes you want to map. 7. Verify that the class information is loaded. 8. Open the Mapping Tool. The following sections describe these steps in detail. You must load the Mapping Tool before you load the classes that you want to map. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 96 Creating classes You can create classes and their relationships by using either of the following procedures: ♦ Build an object model in the Modeling Tool. In the Modeling Tool, you create the classes and define their relationships and cardinalities. The Modeling Tool automatically creates reference attributes when you define the relationships among classes. Then, synchronize the implementation that generates the classes and link them into ObjectStudio. ♦ Use the Mapping Tool to generate a complete set of classes whose structure duplicates a set of SQL database tables you have loaded into the atlas. For information on creating classes in the Modeling Tool, refer to the ObjectStudio Modeling Tool User’s Guide, P40-3111. To create a set of classes from tables: 1. Select Tools ⇒ Object from Tables from the menu bar. The following dialog box displays: 2. Select the table from which you want to create an object and click OK. A message box displays indicating a class was created from a table. 3. Click OK to close the message box and dialog box. A new object was added to your atlas (already mapped). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 97 Creating tables You can create database tables by using either of the following methods: ♦ Use existing database tables. ♦ Create new database tables using any of the supported SQL database servers. Preparing classes Before you can map classes, you must prepare them by defining their relationships. Although you can define your own relationships by using the Relationship Manager and the Domain Manager in the Workspace, it is recommended that you define the class relationships in the Modeling Tool so that the relationships contain all necessary information. When the Modeling Tool creates a relationship, it creates a special method, initializeRelations. This method includes specific information that the Mapping Tool requires for mapping. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 98 Preparing tables Good relational database design is the best preparation for using your tables with the Mapping Tool. The only special consideration for the Mapping Tool is concurrency management. The Mapping Tool automatically handles concurrency by using optimistic locking. To use the optimistic locking capability in the Mapping Tool, your database must have some way to keep copies of original rows of data for comparison against current rows to determine whether anything has changed. To reduce overhead of optimistic locking, some database designers create a timestamp column for each table in the database. A timestamp column contains the date and time when the data for that table was updated by a user or application. This way, the Mapping Tool only has to check the timestamp column to determine whether a row has been updated. For more information about concurrency management, see “Managing concurrency” on page 126. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 99 Loading database support Before you can access tables in a database, you must load support for the database server you plan to use. To load database server support: 1. Display the Application dialog box by selecting File ⇒ Load application from the Desktop menu. 2. From the Applications dialog box, select the name of the loadable application that corresponds to the DBMS with which you want to work. 3. Click Load. After loading the database application, the system displays a login dialog box. The login box is different depending on the database server. 4. Enter your server name, user name, and password. Because ObjectStudio enumerates your database the first time it interacts with it (after loading the database application), it may take several moments the first time you select Add Table from the main screen of the Mapping Tool. Loading the Mapping Tool To load the Mapping Tool: 1. Display the Application dialog box by selecting File ⇒ Load application from the Desktop menu. 2. From the Applications dialog box, select the Mapping tool. 3. Click Load. The Mapping Tool icon appears on the ObjectStudio desktop. You must load the Mapping Tool before you load the classes that you want to map. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 100 Saving an image To create an image file with the Mapping Tool loaded: 1. In the ObjectStudio desktop, select File ⇒ Save image from the menu bar or Save Image from the Work Area pop-up menu. The Save As dialog box appears. 2. Select the folder where you want to save the image from the Save in dropdown list box. 3. Enter a file name in the File name field. For example, you may want to call the file maptool.img so that it is easy to identify. Do not overwrite the default image file. If you choose to overwrite the default image file, store a copy of the original file in another directory. 4. Click Save to save the image. 5. In the command line for the ObjectStudio icon, change the –iostudio.img parameter to the name of the new image file. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 101 Loading classes After you prepare the classes by creating their relationships and load the Mapping Tool, load the classes you want to map into ObjectStudio. You can load the classes by using the following features: ♦ Modeling Tool ♦ ObjectStudio Desktop The preferred method is to load classes with the Modeling Tool so that all classes in the implementation are available. Using the Modeling Tool When you create a model in the Modeling Tool and generate source code by synchronizing the implementation, the Modeling Tool creates Smalltalk code for all classes in the model and loads all classes into ObjectStudio. To load classes with the Modeling Tool: 1. Open the Modeling Tool. 2. Open the model that contains the classes. 3. Synchronize the implementation to generate source code for the classes if you have not already done so. For complete instructions for using the Modeling Tool, refer to the ObjectStudio Modeling Tool User’s Guide, P40-3111. Using the Desktop You can also load classes directly from the ObjectStudio Desktop, but you must load each class individually. To load a class with the ObjectStudio Desktop: 1. Select File ⇒ Load File from the Desktop menu or Load File from the Work Area pop-up menu. The Open dialog box appears. 2. Select the class that you want to load. 3. Click Open. ObjectStudio loads the selected class. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 102 Verifying class information Before you attempt to map the classes, verify that all necessary information is loaded. Check the following items: ♦ Classes ♦ Relationships ♦ Domains Classes To verify that the classes are loaded: 1. From the ObjectStudio Desktop, open the Class Browser. 2. Check the Classes list for the names of classes you want to map. 3. Close the Class Browser. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 103 Relationships To verify that the relationships are loaded: 1. Open the Workspace. 2. Run the following statement: RelationManager inspect The Inspector appears. 3. Check the list to verify that the relationships are loaded. 4. Close the Inspector. 5. Close the Workspace. Domains To verify that the domains are loaded: 1. Open the Workspace. 2. Run the following statement: DomainManager inspect The Inspector appears. 3. Check the list to verify that the domains are loaded. 4. Close the Inspector. 5. Close the Workspace. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 104 Starting the Mapping Tool Once you have loaded the classes and database support and have logged in to the server, you can start the Mapping Tool. To start the Mapping Tool, double-click the Mapping Tool icon. The Mapping Tool main window appears as shown: Running the sample Sales Order application The sample Sales Order application (described in “Sales Order application” on page 194) is a loadable application that is used in the Relational POF examples. For information about running this application, refer to the ObjectStudio Release Notes, P40-3208. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: The Mapping Tool interface 105 Mapping Tool user interface basics This section describes the Mapping Tool user interface. List boxes The Mapping Tool main window appears when you open the Mapping Tool. It displays the classes and tables that you add to your atlas. It also displays related and mapped classes and tables. The following figure is an example of the Mapping Tool main window: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: Mapping Tool user interface basics 106 Depending on the selected item, list boxes contain different types of information. The following table describes the possible list boxes: For the following items… The corresponding list boxes are… A class in the Atlas list The Related Classes and Mapped Tables list boxes. A primitive attribute in the Atlas list The Mapped Columns list box. A reference attribute in the Atlas list The Mapped Tables list box. A table in the Table list The Related Tables and Mapped Classes list boxes. A column in the Tables list The Mapped Attributes list box. List boxes on the Mapping Tool main window display the classes and tables that you add to the atlas. After adding the classes and tables that you need, you can set primary keys, map primary and reference attributes to columns and tables, and set dependent objects. The Mapping Tool displays classes and tables in a tree view. To expand a node in a tree view, click the plus sign (+) or display the Atlas pop-up menu and select Explore. To collapse a node in a tree view, click the minus sign (−). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: Mapping Tool user interface basics 107 Atlas The Mapping Tool contains a list box that displays the currently open atlases. Each atlas contains the classes you want to map to database tables. The Mapping Tool main window displays the name of the available classes preceded by the class icon ( ). To see the attributes in the class, click the plus sign (+) to expand the node. The following figure shows an example of the classes in the SalesOrder atlas: The following table describes the class and attribute icons used in the Atlas list box: Icon Description Indicates a class, which is an ObjectStudio object that contains attributes and relationships to other classes. Indicates a primitive attribute, which is an attribute of a class in which data is stored. (You can use the Attribute Editor in the Modeling Tool to define the domain of a primitive attribute.) Indicates a reference attribute, which is an attribute that refers to a related class. (You can use the Relationship Editor in the Modeling Tool to define relationships among classes.) Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: Mapping Tool user interface basics 108 Tables The Tables list box, shown in the following figure, displays the database tables that you want to map to classes in the atlas: The following table describes the table and column icons used in the Tables list box: Icon Description Indicates a Table, which is a collection of columns containing related information. Indicates a primary key, which is a column that uniquely identifies the row in the table. The Mapping Tool utilizes the database framework to identify primary keys. Indicates a foreign key, which is a column that contains the information of the primary key in another table. The Mapping Tool assigns this icon to the column after you use it to join two tables. Indicates a column, which is any column in a table other than a primary key or foreign key. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: Mapping Tool user interface basics 109 Related Classes The Related Classes list box shows the ObjectStudio classes that are related to the currently selected class in the Atlas list box. You must define relationships in the Modeling Tool before any classes are displayed in this list box. Mapped Tables The Mapped Tables list box shows the tables that are mapped to the selected class or the tables that are mapped to the selected reference attribute. Mapped Columns The Mapped Columns list box shows the columns that are mapped to the selected primitive attribute. Related Tables The Related Tables list box shows you the tables that are related to the currently selected table in the Tables list box. As you map classes and attributes to tables and columns, the Mapping Tool prompts you to define the necessary joins between tables. Once you have defined the joins, the related tables appear in this list box. Mapped Classes The Mapped Classes list box shows the classes that are mapped to the selected table. Mapped Attributes The Mapped Attributes list box shows the attributes that are mapped to the selected column. Dependent object primitive attributes indicate their depending class in parentheses. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: Mapping Tool user interface basics 110 Menus The Mapping Tool has a menu bar and available pop-up menus. Menu bar The Mapping Tool menu bar gives you access to all services in the tool. The menu bar is available at all times in the Mapping Tool. The following figure shows the Mapping Tool menu bar: The following table describes the Mapping Tool menus: Menu Allows you to File Create, open, close, and save atlases, and exit the Mapping Tool. Edit Edit the selected table or class, set atlas or class preferences, and create reports and queries for an atlas or class. Tools Access object cursors, create classes from tables, and synchronize atlas. Help Access the online help system. Pop-up menus The Mapping Tool also has pop-up menus that provide the same options available on the Edit menu for the currently selected item. To access the popup menus, select an item, and then click mouse button 2. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: Mapping Tool user interface basics 111 Toolbar The toolbar provides access to some file manipulation features, Mapping Tool features, and ObjectStudio features, such as the Class Browser and Workspace. The following figure shows the Mapping Tool toolbar: The following table describes each of the toolbar buttons: Button Function Creates a new atlas. Opens an existing atlas. Closes the currently selected open atlas. Saves the currently selected atlas. Opens the Object Cursor dialog box. Opens ObjectStudio. Opens the ObjectStudio Class Browser. Opens the ObjectStudio Workspace. Opens the ObjectStudio System Transcript. Opens the ObjectStudio Desktop. Opens the Database Notebook. Opens the SQL Window. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the Relational POF Section: Mapping Tool user interface basics 112 7 Building an atlas Atlas basics An atlas is a file that contains all information that the Mapping Tool uses to handle database requests from the application. This information describes how a group of objects maps to the tables in a database. After you create an atlas in the Mapping Tool, anyone can use the atlas to build an ObjectStudio application that uses the objects whose data exists in that database. The main components of the atlas are: ♦ Configuration information about the atlas ♦ A list of brokers that specifies how a given class and its attributes map to one or more of the database tables Multiple atlases The Mapping Tool allows you to have multiple atlases loaded simultaneously. However, the tool will not load an atlas if it contains a class defined in a previously loaded atlas. The Mapping Tool creates instances of application warnings in the MFSystemModel>>errorObject method. Databases and qualifiers You specify the database that contains the tables you want to map for each atlas. You can specify only one database per atlas, but there can be a different database for each atlas. When you specify the database for an atlas, you can also specify the qualifier for the database tables. The qualifier is a text string that precedes the table name. You can specify only one qualifier for all tables in the database. However, you can specify another qualifier for individual tables. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Atlas basics 113 Steps for building an atlas To build an atlas, you load the ObjectStudio classes and database tables for your application into the atlas. Perform the following steps: You must load the Mapping Tool before you load the classes you want to map. 1. Prepare the classes and tables: A. Create or use a set of related classes that form an object model. B. Create or use a set of related database tables. C. Load the classes into ObjectStudio. 2. Create a new atlas. 3. Select the database that contains the tables you want to map from the Database drop-down list. 4. Add the classes to the atlas. 5. Add tables to the atlas. After you create the atlas, you can map the classes, their attributes, and their relationships to the tables and their columns. For more information, see “Mapping basics” on page 135. The following sections describe these steps in detail. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Atlas basics 114 Setting atlas mapping preferences The Mapping Tool allows you to change preferences for the current atlas and associated classes. To set preferences for an atlas: 1. Right-click the atlas, and select Preferences from the pop-up menu. The Atlas Preferences dialog box appears as shown: 2. Select the appropriate Traversal Integrity and Retrieval Integrity options. 3. Select the appropriate check box for the Atlas Setting options. 4. Specify the qualifier delimiter for the database qualifier that applies to the tables used in the atlas; then click Set. 5. Click Close to close the Atlas Preferences dialog box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Setting atlas mapping preferences 115 The following table describes the interface items: Item Description Traversal Integrity Object Pool Indicates that a search for a reference attribute begins with the object pool. If the attribute is not found, the database is searched. Traversal Integrity Database Indicates that the database is searched for a reference attribute, bypassing the object pool. Retrieval Integrity Object Pool Indicates that a search for an object begins with the object pool. If the object is not found, the database is searched. Retrieval Integrity Database Indicates that the database is searched for an object, bypassing the object pool. Atlas Setting Map Inverse Automatically sets the Map Inverse check box in the Join Tables and Lookup Table dialog boxes. Indicates if the Mapping Tool maps the inverse reference attribute when it creates a map. For more information, see “Mapping basics” on page 135. Atlas Setting Concurrency Indicates whether concurrency management is activated to prevent conflicts. Qualifier Delimiter Specifies the delimiter the Mapping Tool uses with the qualifiers specified for the database tables in the Mapping Tool main window. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Setting atlas mapping preferences 116 Creating an atlas To create an atlas: 1. Open the Mapping Tool. 2. Select File ⇒ New from the menu bar. The Mapping Tool creates a new atlas and lists it in the Atlas list. Specifying a database When you specify the associated database, you also specify the qualifiers for the tables in the database. To associate a database with the atlas: 1. In the Mapping Tool main window, select a database from the Database drop-down list. 2. Enter the qualifier for all database tables in the Qualifier field below the Database field if your tables require a qualifier. 3. Click the corresponding Set button. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Creating an atlas 117 Adding classes to the atlas This section describes how to choose which classes to add and how to add classes to the atlas. Determining which classes to add Once you have created your ObjectStudio classes, adding them to the atlas is a simple process. You must include all concrete, abstract, and dependent classes in your atlas. If you do not include abstract classes, they are automatically added by the tool. If there is a common superclass (root class) other than PersistentObject to all your business model classes, it should be included also. The superclass for your business model must be PersistentObject. An abstract class is a class that has no instances. The superclass in a gen-spec can be an abstract class. For example, Customer is an abstract superclass that has two subclasses: Corporate and VAR. In the Mapping Tool, you add only the persistent, nonabstract subclasses to the atlas. The Mapping Tool automatically includes the attributes inherited from the superclass in each of the subclasses. It also adds the superclass to the atlas. This process is true of all gen-specs, not just those with abstract superclasses. The following figure illustrates how the object model corresponds to the tables in the Sales Order application: Customer CORPORATE customerId: String name: String address: Address salesOrder: IdentitySet territory: Territory ADDRESS CUSTOMERID NAME ... VAR ADDRESS Corporate CUSTOMERID DISCOUNT. . . VAR discount: Float Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Adding classes to the atlas 118 Adding classes To add ObjectStudio classes to an atlas: 1. In the Mapping Tool main window, select the atlas to which you want to add the classes. 2. Select Edit ⇒ New ⇒ Class from the menu bar or New Class from the Atlas pop-up menu. The Add Class dialog box appears. It lists only classes derived from PersistentObject, as shown: 3. To limit the available classes to those from the model currently open in the Modeling Tool, check the From Modeling Tool check box. The Modeling Tool does not have to be open to use the Mapping Tool. 4. Select the appropriate classes in the list box. 5. Click OK to close the Add Class dialog box and add the selected classes to the Atlas list box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Adding classes to the atlas 119 Setting class preferences After you add the classes to the atlas, you can set the class preferences. Preferences control integrity and broker implementation. To set class preferences: 1. Right-click the class name, and select Preferences from the pop-up menu. The Class Preferences dialog box appears as shown: 2. Select the appropriate Traversal Integrity and Retrieval Integrity options. 3. Select the appropriate Broker Implementation option. 4. Click Close to close the Class Preferences dialog box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Adding classes to the atlas 120 The following table describes the class preferences options: Item Description Traversal Integrity Object Pool Indicates that a search for a reference object begins with the object pool. If the attribute is not found, the database is searched. Traversal Integrity Database Indicates that the database is searched for a reference object, bypassing the object pool. Traversal Integrity Default Indicates that traversal integrity is taken from the atlas if not explicitly noted. Retrieval Integrity Object Pool Indicates that a search for an object begins with the object pool. If the object is not found, the database is searched. Retrieval Integrity Database Indicates that the database is searched for an object, bypassing the object pool. Retrieval Integrity Default Indicates that retrieval integrity is taken from the atlas if not explicitly noted. Broker Implementation Class-based Indicates that an MFBroker subclass is generated for the class. Use this option if you want to add/change behavior of the broker on a perclass basis. This option is the default. Broker Implementation Instance-based Indicates that an MFBroker instance is created for the class at run time. Use this option to save memory if you want the same behavior for all brokers. Broker Implementation One Global Instance Indicates that the global MFGlobalBroker is used for the class. This option uses the least memory, but you cannot alter MFBroker behavior. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Adding classes to the atlas 121 Using object queries Object queries are a standard ObjectStudio item. This section describes object queries. To access a query: 1. Select a class in the Atlas list box on the Mapping Tool window. 2. Select Queries from the pop-up menu. The Object Query dialog box displays as shown. It displays all classes in the currently open atlas in the Class list box and all queries defined in the ObjectStudio implementation appear in the Queries list box. 3. Select a query from the Queries list box. 4. Click Execute. The Mapping Tool executes the query and attempts to put the results into the selected class object. If it is successful, an Inspector window appears with the results. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Adding classes to the atlas 122 Adding tables to the atlas To add tables from the selected database to the atlas: 1. Select the atlas to which you want to add the tables. 2. Select Edit ⇒ New ⇒ Table from the menu bar or New ⇒ Table from the Atlas pop-up menu. The Add Table dialog box appears as shown: 3. Select the tables you want to add to the atlas. 4. Click OK to close the Add Table dialog box and add the selected tables to the Tables list box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Adding tables to the atlas 123 Specifying a primary key After you add the tables to the atlas, check to see whether the primary keys are specified for each table. The key icon in the Mapping Tool indicates that a column is a primary key. In the Mapping Tool, primary keys are the basis for joining tables. Even if your database application does not allow or require you to specify primary keys explicitly, you have to specify them in your atlas before you can begin mapping. If the primary key is explicitly specified in the database, the Mapping Tool uses that key. Otherwise, you must specify the primary key. To specify a primary key: 1. Select from the Tables list the table for which you want to specify the primary key. 2. Select Edit ⇒ Open from the menu bar or Open from the Table pop-up menu. The Create Mappings dialog box appears as shown: 3. Select the column you want to be the primary key from the Table list. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Specifying a primary key 124 4. Click Edit Column. The Column Editor dialog box appears as shown: 5. Check the Primary Key check box. 6. Click Close to close the Column Editor dialog box. 7. Click Close to close the Create Mappings dialog box. The Mapping Tool changes the column icon to a key ( Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Specifying a primary key ). 125 Managing concurrency “Concurrent access” on page 33 introduced the concept of concurrency and described pessimistic and optimistic locking. The Mapping Tool manages concurrency by seamlessly implementing optimistic locking. Implementing concurrency management You can implement concurrency management for: ♦ Entire atlas ♦ Individual columns For the entire atlas To implement concurrency management for the entire atlas: 1. In the Mapping Tool main window, choose File ⇒ Save from the menu bar. The Save Atlas dialog box appears as shown: 2. Check the Set Concurrency On check box in the Options group. 3. Click Save to save the atlas and implement concurrency management when the Mapping Tool generates the code for the atlas. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Managing concurrency 126 For individual columns By default, the Mapping Tool does not implement concurrency for any column. You must specify concurrency for specific columns in a table before you add it to the atlas. Specifying a single column per table reduces overhead so that your application runs more efficiently. A column created specifically for concurrency management is called a timestamp column; it contains the date and time when the data for that table was updated by a user or application. This way, only the timestamp column has to be checked to determine whether the row was updated. Typically, timestamps are used in Sybase® and SQL databases. If your database contains timestamp columns, open each table in the Mapping Tool and verify that the Concurrency setting for all other columns in the table is turned off. To implement concurrency management for individual columns: 1. In the Mapping Tool main window, select from the Tables list the table that contains the column. 2. Select Edit ⇒ Open from the menu bar or Open from the Table pop-up menu. The Create Mappings dialog box appears. 3. Select the column from the Table list. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Managing concurrency 127 4. Click Edit Column. The Column Editor dialog box appears as shown: 5. Select the column from the Column drop-down list. 6. Check the Concurrency check box. 7. Repeat steps 1–6 for each column (except the timestamp column) in each table. 8. Click Close to close the Column Editor dialog box. The Mapping Tool uses the MFColumn class to set concurrency for columns. MFColumn>>setConcurrencyOn sets concurrency on for a column. MFColumn>>setConcurrencyOff turns concurrency off for a column. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Managing concurrency 128 Concurrency classes and methods The broker and the PersistentID object are responsible for managing the concurrency in the framework. Each instance of MFAtlas has instance variable concurrency. MFAtlas>>setConcurrencyOn turns concurrency on; MFAtlas>>setConcurrencyOff turns concurrency off. If you set the concurrency on, then every time the Mapping Tool reads data from the database, it stores the data in the PersistentID object. Then the next time an update or delete request is sent, the Mapping Tool compares the data that exists in the PersistentID object. If the data is the same, the Mapping Tool successfully completes the transaction. If the data is different, the Mapping Tool generates an error. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Managing concurrency 129 Opening an atlas To open an atlas: 1. In the Mapping Tool main window, select File ⇒ Open from the menu bar. The Open dialog box appears. 2. Select the atlas file that you want to open. 3. Click OK. The Mapping Tool opens the atlas. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Opening an atlas 130 Editing an atlas You can edit an atlas by: ♦ Removing a class ♦ Removing a table ♦ Renaming an atlas ♦ Changing database associations You can also change the mappings in an atlas. (For more information, see “Mapping basics” on page 135.) Removing a class To remove a class from the atlas: 1. Select the class from the Atlas list. 2. Select Edit ⇒ Remove from the menu bar or Remove from the Class pop-up menu. The Mapping Tool removes the class from the atlas and the Atlas list. Removing a table To remove a table from the atlas: 1. Select the table from the Tables list. 2. Select Edit ⇒ Remove from the menu bar or Remove from the Table popup menu. The Mapping Tool removes the table from the atlas and the Tables list. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Editing an atlas 131 Renaming an atlas To change an atlas name: 1. Select the atlas from the Atlas list. 2. Select Edit ⇒ Rename from the menu bar or Rename from the Table popup menu. The Rename Atlas dialog box prompts you for the new atlas name. 3. Enter the new atlas name. 4. Click OK. The Mapping Tool changes the atlas name. Changing database associations To change the database associated with the atlas: 1. Select the atlas from the Atlas list. 2. Select a different database from the Database drop-down list. 3. Enter a new database tables qualifier in the Qualifier field if the tables require a qualifier. You can have different versions of a database (for example, test and production), where the database name is the same. Qualifiers can be used to ensure unique table names. For example, a database named Sales contains a table named Product. In the test version of Sales, the table has no qualifier, so its name is Product. In the production version of Sales, the table name is v1.Product, using a qualifier of v1. 4. Click the corresponding Set button. The Mapping Tool changes the database associated with the selected atlas and its qualifier. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Editing an atlas 132 Synchronizing an atlas After you generate brokers for an atlas by saving it, you can continue to work on the atlas. To confirm that the mappings you specified are still current, synchronize the atlas. To synchronize an atlas: 1. In the Mapping Tool main window, select Tools ⇒ Synchronize Atlas from the menu bar. The Synchronize Atlas dialog box appears as shown: The modifications list displays any changes made to the atlas that invalidate any of your saved mappings. 2. Review the modifications; then click Close. The Mapping Tool closes the Synchronize Atlas dialog box and deletes any mappings that it cannot maintain due to changes in the tables or classes. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Synchronizing an atlas 133 Closing an atlas To close an atlas: 1. Select the atlas from the Atlas list. 2. Select File ⇒ Close from the menu bar. If you have made any modifications to the atlas, the Mapping Tool prompts you to save your changes. 3. Click Yes. The Mapping Tool closes the atlas. Deleting an atlas You can delete an atlas only by using operating system commands, because the atlas is a file. By default, atlas files have a .txt extension. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Building an atlas Section: Closing an atlas 134 8 Relational POF mapping Mapping basics Mapping creates pointers between the object model and the database. Once you define the maps, the application developer can create and run queries against classes in the atlas and save and delete objects without dealing with the complexities of the underlying database structure. Before you begin mapping, you should understand the concepts of types of maps, mapping order, and joins between tables. The Mapping Tool prompts you to define joins as you map relationships among your classes to the tables. Map types The Mapping Tool supports maps that represent the relationships in your class structure as they connect to most database table structures. The Mapping Tool supports the following types of maps: ♦ Class ♦ Primitive attribute ♦ Reference attribute ♦ Constant column Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Mapping basics 135 Within each of these map types there are the following subtypes (for more information, see “Creating maps” on page 141): Map type Class Description (1 Class: 1 Table) Maps one class to one table. Each MFClass contains one or many instances of the table. (1 Class: n Tables) Maps one class to more than one table. Each MFClass contains one or many instances of the table. (n Class(es): 1 Table) Maps one or more classes to one table. Primitive attribute (1 Attribute: n columns) Maps one primitive attribute to one or more columns (fieldNames). This relationship is captured by MFPrimitiveAttrMap object. (1 column: n Attributes) Maps one column (fieldName) to one or more primitive attributes. This relationship is captured by MFPrimitiveAttrMap object. Reference attribute (1,1 Reference Attribute: 1,1 Table) Maps two classes with a 1,1 relationship to two tables with a 1,1 relationship. MFReferenceAttrMap and MFReferenceAttrForeignMap objects capture this relationship. (1,m Reference Attribute: 1,m Table) Maps two classes with a 1,m relationship to two tables with a 1,m relationship (with or without an associative table). MFCollectionReferenceAttrMap object captures this map. (m,m Reference Attribute: m,m Table) Maps two classes with an m,m relationship to two tables with an m,m relationship (with an associative table). MFLookupCollectionReference object captures this map. Maps two or more specialized classes to two or more tables. Maps two or more specialized classes to one table (differentiated by the type field). Gen-spec relationships specify the constants value. Each reference attribute can have multiple reference maps associated with it. A gen-spec class (MFClass) will have superclasses and their subclasses associated with it. Each reference attribute can have multiple instances of maps associated with it (any of the previously mentioned reference attribute maps). Maps a dependent class to another table. MFReferenceDependentMap captures this map. Constant column Maps the field name of a table to a constant value. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Mapping basics 136 Mapping order To most efficiently create maps: 1. Map all primitive attributes to columns. 2. Map all relationships (via reference attributes) to tables. 3. Map all other types of maps. This order is important because you must map either a class to a table or a primitive attribute to a column before you can map a reference attribute to that table. When you map a primitive attribute, the Mapping Tool automatically maps the class to the table. For example, you must establish a map between the SalesOrder class and the SALESORDER table and between the SalesRep class and the SALESREP table before you can map the reference attribute salesRep to the SALESREP table. To do this, you can map a primitive attribute (such as orderNo) to a column (such as SALESORDERNO). When you do this, the Mapping Tool automatically maps the corresponding class and table (for example, SalesOrder to SALESORDER). The following figure shows these steps: Class SalesOrder customer: Customer lineItem: IdentitySet orderDate: Date orderNumber: String orderSys: OrderSys salesRep: SalesRep Table n SALESORDER ORDERCUSTID ORDERDATE ORDERNO ... o p SALESREP REPEMPLOYEEID REPFIRSTNAME ... 1 Class Map 2 Primitive attribute map 3 Reference attribute map Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Mapping basics 137 Joins between tables When you attempt to map a reference attribute to a table, the Mapping Tool prompts you to join the two related tables. Join the two tables by selecting the foreign key and the primary key in the two tables, such as the ORDERSALESREPID column in the SALESORDER table and the REPEMPLOYEEID column in the SALESREP table. The following figure shows this join: SALESORDER Foreign key ORDERSALESREPID ORDERCUSTID ... SALESREP Primary key REPEMPLOYEEID REPFIRSTNAME ... For details on creating a reference attribute map, see “Reference attribute map” on page 144. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Mapping basics 138 Attribute data type conversion If a database does not support a primitive Smalltalk attribute’s data type, conversion methods can be defined. The in method converts the database attribute type for use by Smalltalk; the out method converts the Smalltalk attribute’s type for use by the database. To assign a conversion method to an attribute: 1. Select the attribute from the Atlas list. 2. Click mouse button 2. The menu appears as shown here: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Mapping basics 139 3. Select Preferences. The Attribute Preferences dialog box displays, as shown: 4. Specify the name of each conversion method. 5. Click Close to close the dialog box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Mapping basics 140 Creating maps You can create the following types of maps: ♦ Class ♦ Primitive attribute ♦ Reference attribute ♦ Collapsed gen-spec ♦ Inherited gen-spec ♦ Partitioned class ♦ Lookup table ♦ Dependent object The following sections explain how to create each map type. Class map A class map is a map from an ObjectStudio class to a database table, at the class/table level. A class map means: To find the data for instances of this class, look in table X. Mapping classes to tables happens automatically when you map the primitive attributes. You cannot create these maps explicitly. The purpose of class maps is simply to provide the correct class and table information for attribute and relationship maps. A single class can map to multiple tables. However, the tables must be joined. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 141 Primitive attribute map A primitive attribute map is a map from a primitive attribute in a class to a column in a database table. An attribute map means: To find the data for attribute X, look in column Y in database table Z. You must map each primitive attribute to each column explicitly. When you create the first primitive attribute map from the class to a column, the Mapping Tool automatically creates a class map from the class to the table that contains the mapped column. The following figure shows a primitive attribute map: Class Table SalesOrder SALESORDER customer: Customer lineItem: IdentitySet orderDate: Date orderNumber: String orderSys: OrderSys salesRep: SalesRep ORDERCUSTID ORDERDATE ORDERNO ... Map primitive attributes to columns To map primitive attributes to columns: 1. Select the class or attribute from the Atlas list. 2. Select Edit ⇒ Open from the menu bar or Open from the Class or Attribute pop-up menu. The Create Mappings dialog box displays. If the class is already mapped, the Table drop-down list will display the first of the tables mapped to the class. If there are no tables mapped to the selected class, the first loaded table appears in the Table drop-down list. 3. Select a table from the Table drop-down list. 4. Select the attribute that you want to map from the attribute list. 5. Select from the column list the column to which you want to map the selected attribute. 6. Click Map. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 142 Example In the following figure, the primitive attribute orderNumber of the SalesOrder class is mapped to the ORDERNO column of the SALESORDER table: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 143 Reference attribute map A reference attribute map is a map from a reference attribute in a class to one or more database tables. You map the reference attribute because it indicates the objects that are related to the current object. A reference attribute map means: When you need to find the data for the related object indicated by this reference attribute, look in table X. When you map the relationships among your classes, you can locate an individual object’s corresponding database records. You can also locate the records for the objects that are related to a referenced object. To map a relationship, you map a reference attribute in one class to the table where the data resides for the related class. In the following example, the SalesOrder class has a reference attribute called salesRep, which relates to the SalesRep class. To point to the information in the database, map the reference attribute salesRep in the SalesOrder class to the table where the information for the related class is located, SALESREP, as shown in the following figure: Class Table SalesOrder SALESORDER customer: Customer lineItem: IdentitySet orderDate: Date orderNumber: String orderSys: OrderSys salesRep: SalesRep ORDERCUSTID ORDERDATE ORDERNO ... SALESREP REPEMPLOYEEID REPFIRSTNAME ... The relationship map in the previous figure allows you to look up the sales representative for an instance of a sales order. To create a reference attribute map: 1. Specify the map. 2. Specify the join between tables. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 144 Specifying the map To create a reference attribute map: 1. Verify that you have created your primitive attribute maps. 2. Select the class that contains the reference attribute you want to map. 3. Select Edit ⇒ Open from the menu bar or Open from the Class or Attribute pop-up menu. The Create Mappings dialog box displays. 4. Select the reference attribute that you want to map. 5. Click Map. If you are creating a reference attribute map that has a one-to-one or a one-tomany relationship, the Join Tables dialog box appears. However, if you are creating a many-to-many relationship, you are creating a lookup table map. In that case, the Lookup Table dialog box appears. (For more information, see “Lookup table map” on page 152.) Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 145 Specifying the join If you clicked Map in the Create Mappings dialog box, the Join Tables dialog box appears as shown: To specify joins for reference attribute maps: 1. Select the foreign or primary key of the table in the left list box. The Mapping Tool automatically displays the corresponding table and its valid columns. 2. Select the foreign or primary key of the related table in the right list box. The joined columns are displayed in the Joined Columns list. 3. Click Close to close the dialog box and complete the join. The Mapping Tool completes the map between the reference attribute and the table. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 146 Collapsed gen-spec map The Mapping Tool allows you to map a gen-spec relationship with multiple subclasses to one table. Therefore, the attributes for two or more classes that share a common superclass are stored in a single database table. In this example, the abstract superclass, Product, has two subclasses: ServiceProduct and SoftwareProduct, which correspond to one table called PRODUCT, as shown in the following figure: Classes Table PRODUCT Product PRODID PRODNAME PRODPRIC ... description: String lineItem: IdentitySet partNumber: String SoftwareProduct maintPerc: Float price: SmallInteger ServiceProduct dailyRate: SmallInteger In the Mapping Tool, you do not add the abstract class to the atlas. Instead, the subclasses contain all of their inherited attributes and their native attributes when you add them to the Classes list box. Mapping the gen-spec is simple: map each class to the table; then map the attributes of each class to the table. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 147 For clarity, the following figure shows only the attribute-to-column maps; it does not show the class-to-table maps. Classes Table ServiceProduct PRODUCT partNumber PRODID PRODNAME PRODPRIC PRODMAIN description dailyRate SoftwareProduct partnumber description price maintPerc To create a collapsed gen-spec map: 1. For each specialized class, map the appropriate primitive attributes. 2. Select the column that you want as your constant column. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 148 3. Click Edit Column. The Column Editor dialog box appears as shown: 4. Check the Specify constant value check box. 5. Select the class for which you want to assign a constant value. 6. Use the Value entry field or the Get Database Values button to enter a value in the Value list box. Next, click Add to move the value to the Constants list box. 7. Select the operator from the Operator drop-down list. 8. Click Close to close the Column Editor dialog box and return to the Create Mappings dialog box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 149 Inherited gen-spec map You use an inherited gen-spec map to map gen-spec relationships to tables. Attributes for a superclass are inherited by its subclasses. Attributes are displayed in the superclass in the model. In the Mapping Tool, they appear under the subclass in the Atlas list box. You map the inherited attribute from the subclass to the corresponding column in a table. Create an inherited attribute map the same way you create a primitive attribute map. However, be sure to load only the specialized classes; do not load the generalized class. (For more information, see “Primitive attribute map” on page 142.) Partitioned class map In a partitioned class map, the attributes for one class are stored in two tables in the database. Therefore, you must map the class to both tables. For example, the SalesRep class contains all information on sales representatives. However, in the database, sales representative information is split into the following tables: ♦ SALESREP ♦ SALESREPEXTRA Therefore, the SalesRep class contains primitive attributes that are located in two separate tables. To access the information in both tables, you first map to a primitive attribute in SALESREP. When you attempt to map the primitive attribute salesOffice to the second table (SALESREPEXTRA), the Mapping Tool prompts you to join the two tables. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 150 The following figure illustrates a partitioned class map: Class Table SalesRep SALESREP address: Address employeeID: String personName: PersonName salesOffice: String salesOrder: IdentitySet territory: IdentitySet n REPEMPLOYEEID o REPFIRSTNAME ... SALESREPEXTRA REPSALESOFFICE REPEMPLYEEID ... Map 1 Represents a map to the primary key. Map 2 Represents a primitive-attribute-tocolumn map in the seconday table. To create a partitioned class map: 1. Select the primitive attribute. 2 Select the column that you want to map. 3. Click Map. The Join Tables dialog box appears when the primitive attribute mapping is to a second table. 4. Join the tables as described in “Joins between tables” on page 138. 5. Click Close. Map the class’s attribute to the primary key in the first table only. Do not map it to the primary key in the second table. The join enables the Mapping Tool to locate the data in the second table. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 151 Lookup table map A lookup table map allows you to map two classes that have a many-to-many relationship to their respective tables in the database. It is a variation of a reference attribute map. In your object model, a many-to-many relationship exists when zero or more instances of one class relate to zero or more instances of another class. For example, a sales representative can have more than one territory, and a territory can have more than one sales representative. Therefore, the cardinality between the classes SalesRep and Territory is [1,m]/[1,m]. The following figure shows a many-to-many relationship: SalesRep address: Address employeeId: String personName: PersonName salesOffice: String salesOrder: IdentitySet territory: IdentitySet Territory Territory 1..* 1..* SalesRep customer: IdentitySet salesRep: IdentitySet territoryId: String territoryName: String The Mapping Tool supports many-to-many joins with lookup tables. A lookup table contains a primary key for each table to be joined. For example, the REPTERRITORY lookup table contains the REPEMPLOYEEID primary key from the SALESREP table and the TERRITORYID primary key from the TERRITORY table. This primary key combination is how the database uniquely identifies a territory’s sales representative or a sales representative’s territory. The following figure shows the join using a lookup table: Lookup Table REPTERRITORY TERRITORYID REPEMPLOYEEID SALESREP REPEMPLOYEEID REPFIRSTNAME . . . TERRITORY TERRITORYID Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps TERRITORYNAME 152 You create a lookup table map the same way you would a reference attribute map. The difference is that when you map one class’s reference attribute to the table where the data for the related class is stored, the Mapping Tool checks to see whether there is a many-to-many cardinality between the classes. If the cardinality is m:m, the Mapping Tool displays the Lookup Table dialog box instead of the Join Tables dialog box. Procedure If you click Map in the Create Mappings dialog box, the Lookup Table dialog box displays as shown: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 153 The Lookup Table dialog box shows column information for three types of tables. To specify joins for lookup table maps: 1. Select the lookup table from the Lookup Table drop-down list. The columns for the selected table appear in the two center list boxes. The leftmost list box shows the columns for the table selected in the Table drop-down list box. The rightmost list box shows the columns for the table selected in the Related Table drop-down list. 2. Select the column that you want to map from the Table columns list (leftmost list box). 3. Select the corresponding column in the left Lookup Table columns list box. 4. Click Join. 5. Select the column that you want to map from the Related Table columns list (rightmost list box). 6. Select the corresponding column in the right Lookup Table columns list box. 7. Click Join. 8. Click Close. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 154 Example To create a lookup table map using the Sales Order demo, you can map SalesRep to SALESREP and Territory to TERRITORY: 1. In the Create Mappings dialog box, select the Territory reference attribute in the SalesRep class and then select the TERRITORY table. 2. Click Map. The Mapping Tool displays the Lookup Table dialog box. 3. Select the RepTerritory table from the Lookup Table drop-down list. The columns from the RepTerritory table appear in both column list boxes for the lookup table. 4. Select the repEmployeeID column from the Table columns list box (leftmost list box), because it is the primary key for the SalesRep table. 5. Select the repEmployeeID column from the left Lookup Table columns list box; then click Join. 6. Select the territoryID column from the Related Table columns list box (rightmost list box), because it is the primary key for the Territory table. 7. Select the territoryID column from the right Lookup Table columns list box; then click Join. 8. Click Close to close the Lookup Table dialog box. The Mapping Tool automatically maps the reference attribute to the corresponding table. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 155 Dependent object map In a dependent object map, the reference attribute pointing to a dependent class is declared a dependent object. A dependent object is an object whose data is dependent on the class to which it is related. Use dependent objects to represent self-contained information that can refer to multiple classes. The dependent class is a class in the model whose attributes are meaningless except in the context of the parent class. Common examples of dependent objects are PersonName and Address. The dependent class can be shared among several classes and, typically, is referred to as a design object. The dependent class is not added to the atlas. Instead, in each class that uses the dependent class, you define the reference attribute as a dependent object and map its attributes to the table to which they correspond in this particular class. In this way, the dependent class can be mapped to several different tables. For example, Address could be a dependent object of SalesRep and of Customer as shown in the following figure: Parent classes SalesRep address: Address employeeId: String personName: PersonName salesOffice: String salesOrder: IdentitySet territory: IdentitySet Dependent object Address Address 1 1 SalesRep street: String city: String state: String zip: String phone: String 1 Customer Customer address: Address customerId: String name: String salesOrder: IdentitySet territory: territory Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 1 Address 156 Dependent objects do not exist in a relational database schema. Therefore, when you define a dependent object, you need to indicate where the data for that object is located in the database. In the Mapping Tool, you indicate the location by mapping the attributes of the dependent object with the columns of the table where the data is located, as shown in the following figure: Dependent object Table SALESREP REPEMPLOYEEID REPCITY REPPHONE Address street: String city: String state: String zip: string phone: String Once you define the dependent object, the Mapping Tool automatically maps the class to which the dependent object refers to the corresponding table, if you have not already done so. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 157 To create a dependent object map: 1. Select the reference attribute that you want to map. 2. Click Dependent Object. The Dependent Object Editor dialog box displays as shown: The dependent object’s class and its attributes are displayed on the left. The corresponding table and its columns are displayed on the right. 3. Select the attribute. 4. Select the corresponding column. 5. Click Map. 6. Repeat steps 3–5 for each primitive attribute you want to map. 7. Click Close when you are finished. The Mapping Tool automatically maps the class to which the dependent object is related to the corresponding table. Define the dependent object in each class that it appears in. For example, after defining address as a dependent object of SalesRep, you would repeat the process for the classes VAR and Corporate. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Creating maps 158 Saving an atlas When you save an atlas, you save all maps currently defined in it. Therefore, there is nothing to save until you create some maps. It is important to save your maps often, because if you define a map incorrectly and cannot retrace your steps, you can close the atlas to remove the unwanted map without losing the rest of your work. This section describes saving an atlas by using the defaults and specifying optional save settings. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Saving an atlas 159 Using defaults The Save Atlas dialog box specifies values for all save options. The Mapping Tool uses values specified in the maptool.ini file for the default values in the Save Atlas dialog box. To save an atlas using the default save settings: 1. Select File ⇒ Save from the menu bar. The Save Atlas dialog box appears as shown: By default, the Mapping Tool assigns a file name made from the atlas name for a new atlas. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Saving an atlas 160 2. Click Save. The Mapping Tool saves the atlas with the current name of the atlas as a text file in the directory specified in the Save Options dialog box. 3. If you modified the brokers without using the Mapping Tool interface (using the Class Browser or the Text Editor), the Mapping Tool detects the changes and displays the Save Warnings dialog box as shown: 4. In the Save Warnings dialog box, select the warning that refers to the method conflict in the Warning messages list. 5. Select the class that contains the method in conflict in the Classes list. 6. Select the method in the Methods in contention list. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Saving an atlas 161 7. Click Merge. The Merge method source code dialog box appears as shown: The Target field displays the source code for the model, and the Merge field displays the source code for the implementation. The Result textediting field shows the code that will be used in the new implementation. 8. Edit the source code in the Result text-editing field. 9. Click OK to save the new method source code and close the dialog box. 10. Resolve any other conflicts. 11. Click Continue. The Mapping Tool continues the synchronization. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Saving an atlas 162 Using optional settings Instead of simply accepting the default save settings, you can specify settings for: ♦ Classes ♦ Methods ♦ Files Specify this information before you click Save. Saving class information The Mapping Tool allows you to specify the following class information when you save the atlas: ♦ Broker class file name ♦ Broker name ♦ Whether to display class conflict warnings ♦ Default superclass To specify class information: 1. To change the file name of the generated class file for any of the brokers: A. In the Save Atlas dialog box, select the class in the Broker Classes to be saved list. B. Enter the new broker name in the Broker file name field. 2. To change the name of any of the broker classes: A. Select the class in the Classes to be saved list. B. Enter the name of the selected class in the Broker Name field. 3. Specify whether you want to display warnings when there is a conflict with the brokers in the atlas file by checking or unchecking the Display warnings check box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Saving an atlas 163 4. Click More Options. The Save Options dialog box appears as shown: 5. To change the default superclass for the atlas, select a new superclass from the Default superclass drop-down list. 6. Click OK to close the Save Options dialog box and return to the Save Atlas dialog box. The Default superclass should exist in the Smalltalk image. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Saving an atlas 164 Saving method information The Mapping Tool allows you to specify whether to regenerate methods that have been modified. To specify method information: 1. In the Save Atlas dialog box, click More Options. The Save Options dialog box appears. 2. Select the appropriate radio button to specify how the Mapping Tool should handle method conflicts: ♦ Regenerated—ObjectStudio regenerates any modified methods. ♦ Ignored—ObjectStudio ignores any changes in generated methods. 3. Click OK to close the Save Options dialog box and return to the Save Atlas dialog box. Saving file information The Mapping Tool allows you to specify the following file information: ♦ Atlas file name ♦ Directory in which to save the atlas file ♦ Whether to set concurrency For information about changing class file names, see “Saving class information” on page 163. To specify file information: 1. To save the atlas using a name other than the atlas name, enter a new atlas file name in the Name field in the Save Atlas dialog box. 2. Click Browse to specify the directory in which to save the atlas file. 3. Specify whether the Mapping Tool should handle concurrency for the atlas by checking or unchecking the Set Concurrency check box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Saving an atlas 165 Printing mapping information This section describes how to print the mapping reports. Report types You can print the following types of reports: ♦ Atlas ♦ Class ♦ Primitive attribute ♦ Reference attribute ♦ Table ♦ Column Regardless of the type of report you generate, the report header includes the: ♦ Name of the element for which you are generating the report ♦ Mapping Tool version ♦ Report date and time Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Printing mapping information 166 The reports consist of composite information for the specified object including all information on the elements that comprise that object. The following table describes the information for each type of report: Element Information Atlas Lists all atlas classes and tables, and their respective information, including the type of traversal integrity and retrieval integrity and, for classes, broker implementation. Class Lists the mapped tables; constant column values (if any); the type of traversal integrity, retrieval integrity, and broker implementation; and information for its primitive and reference attributes. Primitive attribute Lists the attribute’s mapped columns. Reference attribute Lists the attribute’s referenced classes and mapped tables. Table Lists the mapped classes, related tables, and the information on each of its columns. Column Lists the column’s mapped attributes and whether it is a primary or foreign key. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Printing mapping information 167 Generating reports To generate an object model report: 1. In the Mapping Tool main window, select an element in either the Atlas or Table list box. 2. Choose Report from the item’s pop-up menu or Edit ⇒ Report. The Specify Report Destination dialog box appears as shown: 3. Specify the report destination; then click OK. If you specified to print the file, the Print dialog box appears. However, if you specified to send the report to a text file or a rich text file (RTF), the Save As dialog box appears. 4. If you are sending the report to a printer, specify the print information; then click OK. 5. If you are saving the report to a file, specify the file name and destination; then click OK. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF mapping Section: Printing mapping information 168 9 Completing an application Saving and deleting objects Objects do not automatically persist outside the life span of your application session. Saving and deleting objects is the responsibility of the application developer. Before you can save or delete an object, you must ensure that its class is persistent. Adding a class to the atlas for your application and mapping that class and its attributes to the database makes the class persistent. The object must also have a primary attribute, defined in the atlas as the primary key in the corresponding database table. For details on building an atlas, see “Atlas basics” on page 113 for more information. The Mapping Tool provides a full set of methods for saving and deleting objects. These methods execute persistent operations against the database. For most operations, you can use the save and delete methods; other methods handle more complex operations. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Completing an application Section: Saving and deleting objects 169 Available methods The methods are listed in the following table: Method Description save Saves only the base object. saveAll Saves the object and all related objects. saveComposite Saves the object and all of its part objects, where the object and its part objects form an aggregation. delete Deletes only the object. Understanding which methods to use Use the save and delete methods for saving and deleting objects. The following figure shows a part of the Sales Order application model. For the purpose of explaining how the save, saveComposite, and saveAll methods differ, in this example the SalesOrder class has two specializations: Domestic and International. These two classes are not present in the sample application: SalesOrder customer: Customer lineItem: IdentitySet orderDate: Date orderNumber: String orderSys: Ordersys LineItem LineItem 0..1 lineNumber: String 0..* product: Product SalesOrder quantity: SmallInteger salesOrder: SalesOrder 0..* LineItem Domestic International Product 1 Product description: String lineItem: IdentitySet partNumber: String Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Completing an application Section: Saving and deleting objects 170 A SalesOrder is a generalization whose part class is LineItem. Each line item has an association with a Product. Suppose your application retrieved a set of related objects, consisting of one instance of each object in the model. The following table shows what would be saved if you executed each of the three save methods for an instance of SalesOrder: Method Instance objects saved aSalesOrder save aSalesOrder aSalesOrder saveComposite aSalesOrder, aLineItem aSalesOrder saveAll aSalesOrder, aLineItem, aProduct Specializations of a gen-spec relationship are not saved when you save an instance of the superclass. The Domestic class inherits the aggregation relationship that class SalesOrder has with LineItem. The following table shows what would be saved if you executed each of the three save methods for an instance of Domestic: Method Instance objects saved aDomestic save aDomestic aDomestic saveComposite aDomestic, aLineItem aDomestic saveAll aDomestic, aLineItem, aProduct Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Completing an application Section: Saving and deleting objects 171 Testing maps You must ensure that the maps in your atlas correctly reflect your object model and your relational database. Reasons for testing It is important to test your maps for the following reasons: ♦ The Mapping Tool implicitly captures some of the semantic information about your relational database and applies it to your object model. For example, in mapping a reference attribute to a table, the Mapping Tool assumes that the cardinality of the object model correctly reflects the cardinality between the two tables in the relational database. Also, when you map a class across multiple tables, the implied cardinality between the relational tables is one-to-one. ♦ If you are building a prototype, you need to test for potential inconsistencies in either your relational database, if your database was created from the object model, or your object model, if your object model is derived from an existing relational database schema. ♦ Testing reveals whether you incorrectly defined a map or a join between columns. The following section explains how to test your maps using the Object Cursor option. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Completing an application Section: Testing maps 172 Using the object cursor for testing The object cursor is the primary tool for testing maps in your atlas. You can use the object cursor and the ObjectStudio Inspector to walk through the object structure and look for inconsistencies in your maps. Procedure To use the object cursor to test your maps: 1. Select a class in the Classes list box in the Mapping Tool main window. 2. Select Tools ⇒ Object Cursor from the menu bar. The Object Cursor dialog box appears as shown: The selected class appears in the Class drop-down list box. You can select a different class from the drop-down list box. The drop-down list box contains only those classes that you have added to the atlas. 3. Click Open Cursor to open an object cursor. If there are objects in the tables for this selected class, the Next button is enabled. Click Next to display an object in the Objects list box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Completing an application Section: Testing maps 173 4. Click Inspect or double-click an item to open the Inspector window for the selected object as shown: 5. Use the Inspector to walk through the structure of the object. The Inspector shows the attributes for the instance of the object in the editor. Double-clicking an attribute allows you to edit the object for this attribute. If the object is a primitive object (such as a String, Symbol, Date, SmallInteger, etc.), it is displayed in an entry field. If it is a complex object, another Inspector window opens. 6. Test each type of map. Ensure that: ♦ Each primitive attribute contains the proper data. ♦ You have created the necessary dependent objects. Double-click each dependent object to see whether it contains the proper data. ♦ All mapped reference attributes return the correct objects. Also, see if you are getting the correct number of objects. For example, if you defined a cardinality between SalesOrder and LineItem of zero or more, you should have a collection of LineItem objects for the lineItem attribute of SalesOrder. ♦ Classes you mapped to multiple tables contain all correct data for their attributes from each table. Resolving map inconsistencies The most efficient way to resolve inconsistencies in a map is to delete the map and remap it. To delete the map, select the class or attribute from the Classes list box and the corresponding table or column in the Tables list box and then click Unmap. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Completing an application Section: Testing maps 174 Deploying an application To deploy an application, you must: ♦ Prepare the application ♦ Save an image Preparing the application You must do the following to prepare an application: ♦ Provide login capabilities. For your users to be able to log on to the necessary database, you must provide login capabilities in your application. ♦ Assign a database handle. After the user is logged on to the database, you must ensure that the database information is passed to the POF. Saving an image After you prepare an application, you must save an image of the application using the Program Generator with the whole application loaded. For information about using the Program Generator, refer to the ObjectStudio User’s Guide, P40-3201. You then ship the generated image and executable along with the supporting DLLs to your customers. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Completing an application Section: Deploying an application 175 10 Relational POF administration MAPTOOL.INI file The MAPTOOL.INI file allows you to define default directories and system settings. The MAPTOOL.INI file has Mapping Tool and synchronization sections. Mapping Tool parameters The following table identifies the Mapping Tool parameters in the MAPTOOL.INI file: Parameter Default value Purpose path C:\Program Files\ModTool\Map Location of Mapping Tool files. interfacePath C:\Program Files \ModTool\Map\View Location for user interface controllers created with the Designer. iconPath C:\Program Files\ModTool\icons Location of icon files. helpIniFile MAPHELP.INI Name of the help initialization file. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF administration Section: MAPTOOL.INI file 176 Synchronization parameters The following table identifies the synchronization parameters in the MAPTOOL.INI file: Parameter Default value Purpose errorClassName ApplicationError Class that application errors should use. regenerateUserModifiedMethod true Default setting whether user modified brokers should always be regenerated. rootDirectory C:\Program Files \ModTool\app\brokers Location for storing generated Smalltalk broker class files. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Relational POF administration Section: MAPTOOL.INI file 177 11 Introduction to the UniSQL POF Purpose The purpose of the UniSQL POF is to integrate a UniSQL Server database management system and ObjectStudio. This integration must support all of the object-oriented extensions of a UniSQL Server database and therefore cannot be based on standard SQL. To achieve this goal, the UniSQL API has been mapped into ObjectStudio and is wrapped with a set of classes to simplify the usage in a user-developed application (within the scope of the Persistent Object FrameWork). This interface supports only a 1:1 mapping of class structures between UniSQL and ObjectStudio. Because UniSQL supports the same sort of structures as those found in Smalltalk, the mapping must be as transparent as possible. If the Smalltalk class structure and the UniSQL class structure are the same, there is no need to map them. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the UniSQL POF Section: Purpose 178 Development process overview This section provides a broad overview of how to develop an application using the UniSQL POF. For a description of the sample applications, which provide step-by-step examples of the development process, see “UniSQL POF sample applications” on page 183. Development procedure To develop an application, follow this general procedure: 1. Design a business model using the ObjectStudio Modeling Tool. 2. Generate the database schema using the UniSQL Schema Generator. 3. Generate Smalltalk classes and resolve any keyword conflicts. Design a business model Use the ObjectStudio Modeling Tool to create a model of your business objects. Or, if you already have a model that you want to use, open it. For information about using the Modeling Tool, refer to the ObjectStudio Modeling Tool User’s Guide, P40-3111. Class names in a UniSQL Server database are always in lowercase. Smalltalk is case-sensitive—class names can contain both uppercase and lowercase characters. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the UniSQL POF Section: Development process overview 179 Generate a database schema To generate a database schema, run the UniSQL Schema Generator. The following form appears: The default superclass can be used to change inheritance for all classes in the UniSQL DDL script. For example, if the default superclass is #Cars, the script for these classes is: CREATE CLASS CarModel AS SUBCLASS OF Cars; CREATE CLASS CarOption AS SUBCLASS OF Cars; …. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the UniSQL POF Section: Development process overview 180 The following table describes the Schema Generator buttons: To... Click... See the classes in a model. View Search for a file. Browse Create a UniSQL SQL DDL script for the selected classes. Generate Run UniSQL’s Visual SQL editor and display the DDL script. Visual SQL Exit the Schema Generator. Close First, select all of the classes that you want to include in the implementation. Then enter a file name and click Generate. A UniSQL SQL DDL script is created for the classes previously defined in the business model. To view the UniSQL SQL DDL script, click Visual SQL; then log on to the UniSQL Server database. A window displays the script, as depicted in the following figure: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the UniSQL POF Section: Development process overview 181 You can resolve keyword conflicts by modifying the script (for a specific example, see “Creating a database schema” on page 219). Click Run to execute the script and implement the changes; then commit the changes and close Visual SQL. Generate Smalltalk classes To generate Smalltalk classes from the business model, use the Synchronization implementation option from the Modeling Tool (for a specific example, see “Creating Smalltalk classes” on page 221). Synchronization includes: ♦ Selecting the classes to synchronize ♦ Setting the default superclass to PersistentObject Persistent Smalltalk classes inherit from the PersistentObject class. For more information, see “PersistentObject” on page 35. After creating Smalltalk classes, you may need to create a map class to resolve conflicts with class or attribute names, or convert unsupported data types (for more information, see “Mapping overview” on page 185 and “Mapping a database schema to an object hierarchy” on page 223). When an initialize method is created and saved, the map is automatically loaded. To load the map file automatically the next time you run your application, edit the application’s initialization file, ObjectStudio\w32\cls\Lappiniw.cls (Identity Dictionary subclass), to include the map, such as: dict at: #'MyAppMap' put: 'pathname\appmap.cls'. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the UniSQL POF Section: Development process overview 182 UniSQL POF sample applications Two sample applications are provided with the UniSQL POF as examples of how to develop applications in ObjectStudio and access a UniSQL Server database. CarSale tutorial The CarSale tutorial, CARSALE.TXT, walks you through the process of implementing a UniSQL schema and mapping a UniSQL schema to an ObjectStudio class hierarchy. For specific information about the CarSale tutorial, see “CarSale tutorial” on page 216. Paradise demo application The Paradise demo application, PARADISE.TXT, demonstrates how to retrieve and manipulate database objects. For specific information about the Paradise demo application, see “Paradise demo” on page 229. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the UniSQL POF Section: Development process overview 183 Database connections logon To log on to a database, open the workspace and enter the code in the logon example. If the logon fails, an inspector window is displayed. To see the error description, check the description variable. If the logon is successful, the objects are accessible. logon Description This method establishes a connection with the specified database. Example [ UFDatabase logon: #<your userid> password: #<your password>' database: #<your database>. ] on: POFUFLogonError do: [ :exp | exp inspect ]. logoff To log off the database, execute the code in the logoff example. logoff Description This method disconnects the current database. Example UFDatabase logoff. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Introduction to the UniSQL POF Section: Database connections 184 12 UniSQL POF mapping Mapping overview The UniSQL POF supports a 1:1 mapping of class structures between UniSQL and ObjectStudio. The UFSmalltalkToDatabaseMaps class references all available maps. On initialization, UFSmalltalkToDatabaseMaps creates a global instance, SmalltalkToDatabaseMaps. This instance contains references to all maps that have been initialized or maps for which a user has defined mapping information. SmalltalkToDatabaseMaps has two instance variables: Variable Description databaseNameMap An IdentityDictionary; key is the database class name, and value is the map for this class. smalltalkNameMap An IdentityDictionary; key is the Smalltalk class name, and value is the map for this class. SmalltalkToDatabaseMaps is responsible for knowing and generating the maps for all PersistentObject subclasses and can retrieve a map for either a Smalltalk class name or a database class name. Once a map is retrieved from SmalltalkToDatabaseMaps, it is initialized. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: UniSQL POF mapping Section: Mapping overview 185 If the Smalltalk classes and the database classes do not have keyword conflicts, you do not have to map them. You must create a map to resolve keyword conflicts in the following situations: ♦ A Smalltalk class and its corresponding database class are named differently. ♦ A Smalltalk attribute and its corresponding database attribute are named differently. ♦ The database does not support the Smalltalk attribute’s data type. For example, UniSQL Server does not support Boolean; therefore, any attribute whose data type is Boolean must be converted to another data type, such as char(3). Each Smalltalk class that can be persistent must be inherited from the PersistentObject class (for more information, see “PersistentObject” on page 35). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: UniSQL POF mapping Section: Mapping overview 186 Creating a map class If after generating the Smalltalk classes for your application, any of the conditions previously listed in “Mapping overview” apply, you must create a map class. Use the ObjectStudio Class Browser to map specific Smalltalk classes to database classes: 1. Select UFSmalltalkToDatabaseMaps from the Class Browser. 2. Select Class ⇒ New from the menu bar to create a subclass. 3. Verify that UFSmalltalkToDatabaseMaps is the superclass; then enter a class name for your map file. UniSQL class names are represented in lowercase; Smalltalk class names are represented in mixed-case. 4. Click OK and then save the file. The following form appears: 5. Select the newly created map subclass; then click the Class radio button to create a class method. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: UniSQL POF mapping Section: Creating a map class 187 6. To create an initialize method, select Method ⇒ New from the menu bar; then enter the necessary mapping information in the source window as in the following example: initialize | aMap anAttribute | 7. To map a different Smalltalk class name and database class name, enter the following code: aMap := UFClassMap new. aMap databaseName: #dbclass; smalltalkName: #SmClass. SmalltalkToDatabaseMaps addMap: aMap. 8. To map a different Smalltalk attribute name and a database attribute name for an object that has the same name in Smalltalk and the database, enter the following code: aMap := UFClassMap new. aMap databaseName: #object; smalltalkName: #Object. anAttribute := UFAttributeToColumnMap new. anAttribute databaseName: #dbattrib; smalltalkName: #smAttrib. aMap userDefinedPersistentAttributeMapsAdd: anAttribute. SmalltalkToDatabaseMaps addMap: aMap. 9. To convert a Smalltalk attribute type to a database-compatible data type, enter the following code: aMap := UFClassMap new. aMap databaseName: #object; smalltalkName: #Object. anAttribute := UFAttributeToColumnMap new. anAttribute databaseName: #dbattrib; smalltalkName: #smAttrib; inConvertMethod: #inMethod; outConvertMethod: #outMethod. aMap userDefinedPersistentAttributeMapsAdd: anAttribute. SmalltalkToDatabaseMaps addMap: aMap. For specific examples, see “Mapping a database schema to an object hierarchy” on page 223 in the CarSale tutorial. When you are finished entering map statements, save the initialize method. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: UniSQL POF mapping Section: Creating a map class 188 13 POF exception handling Common exceptions The following exception classes are common to the Relational POF and the UniSQL POF. POFAbstractClassError POFAbstractClassError, the POF abstract class error class, is the root of the POF exceptions thrown by PersistencyBrokerManager. It should not be signaled. POFAbstractError POFAbstractError, the POF abstract error class, is the root of the POF exceptions. It should not be signaled. POFCursorAlreadyOpen The POFCursorAlreadyOpen error is signaled when the cursor upon which the open action is performed already is open. POFCursorNotOpen The POFCursorNotOpen error is signaled when the cursor upon which the current action is performed is not open. POFCursorNotPositioned The POFCursorNotPositioned error is signaled when the cursor upon which the current action is performed is not positioned. POFError The POFError exception is a generic error that is signaled when an error occurs in the Persistent Storage. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: POF exception handling Section: Common exceptions 189 POFHasDifferentBrokersForClass The POFHasDifferentBrokersForClass exception is thrown if there are different brokers for the specified class in the relational system when the brokers are about to be generated. POFNoActiveTransaction The POFNoActiveTransaction exception is thrown on if a #commit or #rollback is being issued without a current transaction being active. POFNoBrokerForClass The POFNoBrokerForClass exception is thrown if no broker exists for the specified class in the relational system. POFNoBrokerForService POFNoBrokerForService is an exception thrown on errors from the POF. This exception can happen if no broker exists for the specified class and service combination or if the mapping information is wrong. POFNotFound The POFNotFound error is signaled when no data was found for the operation performed by POF (for example, no data matching the search criteria or no next record for cursor). POFObjectNotPersistent The POFObjectNotPersistent error is signaled when a persistency operation is being performed on an object that does not have a persistent shadow (for example, a newly created object is being sent the #delete method). Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: POF exception handling Section: Common exceptions 190 Relational POF exceptions The following exception classes apply to the Relational POF only. POFIllegalOperation The POFIllegalOperation exception is thrown in case of illegal operation for the MFClass. POFObjectHasChanged The POFObjectHasChanged error is signaled when the POF detects that an object has changed in the persistent storage since last read. The error is triggered only if concurrency is enabled. POFNoMapForClass The POFNoMapForClass exception is thrown if there is no class to MFClass map defined in the broker. POFNoMappedTablesForClass The POFNoMappedTablesForClass exception is thrown if there are no tables mapped for the MFClass. POFNotUnique The POFNotUnique error is signaled when the result set is not unique. This error is normally signaled when the primary key definition is wrong. POFNoValueForColumn The POFNoValueForColumn exception is thrown if the statement generator cannot find the value for a column. POFNoValueForConstantColumn The POFNoValueForConstantColumn exception is thrown if the statement generator cannot find the value for a constant column. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: POF exception handling Section: Relational POF exceptions 191 UniSQL POF exceptions The following exception classes apply to the UniSQL POF only. POFUFError POFUFError is an exception thrown on UniSQL errors. The exception is not resumable, since UniSQL sent an unexpected message, and the database can be in an undefined state. The code will contain the error number returned from the database, and exString, or description, will return the error text. For further information, refer to the UniSQL software documentation for Error messages. This exception will be raised only from the UniSQLDLL class. All methods in UniSQLDLL can raise this error. POFUFLogonError POFUFLogonError indicates a failure logging on the database. POFUFMappingError POFUFMappingError is an exception thrown on errors from the POF. This exception can happen if it is not possible to map a Smalltalk class to a database class, or if the mapping information is wrong. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: POF exception handling Section: UniSQL POF exceptions 192 POFUFParseError POFUFParseError is an exception thrown on UniSQL parsing errors. The code will contain the error number returned from the database, and exString, or description, will return the error text. POFUFParseError will contain the parseErrors array of the individual errors returned when parsing an SQL statement. The individual parseErrors elements describe each error in the statement. The content of the POFUFParseError variable parseErrors is an array of POFUFParseErrorDescription. Each instance of POFUFParseErrorDescription represents one error detected in the supplied SQL statement. For further information, refer to the UniSQL software documentation for error messages. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: POF exception handling Section: UniSQL POF exceptions 193 A Sales Order application Sample application overview This appendix provides information on the sample application that is shipped with the Mapping Tool. The sample application includes the SalesOrder object model and a set of database tables that can be mapped to the classes in the SalesOrder object model. The model and tables are provided on the Mapping Tool installation media. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Sample application overview 194 Object model structure The object model for the Sales Order application radiates outward from the SalesOrder class. A sales order has a unique order number and one or more line items. A line item has a line number, a quantity, and a product. A product has a part number and a description and can be either a service product or a software product. A service product has a daily rate attribute, while a software product has a maintenance percentage. (This attribute indicates what percentage of the product price is charged for maintenance.) A sales order naturally has a customer. The customer has an ID, a name, and a sales order. Each customer has one or more sales orders. The customer can be either a corporation or a VAR (value-added reseller). Every sales order also has a sales representative. The sales representative has an employee ID, zero or more sales orders, and one or more territories. Each territory has an ID, a name, and contains (in the model, is related to) zero or more customers. Each territory has one or more sales representatives. Because the relationship between SalesRep and Territory is many-to-many, there is a lookup table between the corresponding two tables on the database side. The SalesRep and Customer classes share a dependent object called Address, which consists of street, city, state, and zip code. This dependent object allows the behavior for an address to be shared by the two classes. SalesRep and Customer have a reference attribute that points to the Address class. As a dependent object, Address does not have a reference attribute pointing to either SalesRep or Customer. An instance of Address has no meaning except in the context of an instance of SalesRep or Customer. The application would never start with an instance of Address, then attempt to find the SalesRep or Customer to which it belonged. The SalesRep class has another dependent object, PersonName. PersonName and Address are common examples of dependent classes. They have certain attributes and behaviors that might be shared by many other classes, but an instance of the dependent class has no meaning without its parent object. In a relational database, the dependent object usually corresponds to one or more columns (such as LASTNAME, FIRSTNAME) that appear in more than one table. These columns compose an object and have associated behavior that is the same wherever they appear. Therefore, it makes sense to model these columns as a separate dependent object, so that the behavior need be implemented only once on the object side. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Object model structure 195 The following figure shows the SalesOrder model in UML format, which was created using the Modeling Tool. The figure shows the classes in the model, the relationships among the classes, and the cardinalities of those relationships. Territory Customer Customer customer: IdentitySet salesRep: IdentitySet territoryId: String territoryName: String 1..* 0..* 1 Territory Customer 1 Address SalesRep 1 SalesRep 1 Address city: String phone: String state: String street: String zip: String 1 SalesOrder address: Address customerId: String name: String salesOrder: IdentitySet territory: Territory Corporate Territory 1..* 1 Address Customer SalesRep address: Address employeeId: String personName: PersonName salesOffice: String salesOrder: IdentitySet territory: IdentitySet 1 discount: Float SalesOrder SalesOrder 1 0..* SalesRep customer: Customer lineItem: IdentitySet orderDate: Date orderNumber: String orderSys: Ordersys salesRep: SalesRep PersonName 0..1 SalesOrder SalesRep VAR 0..* 1 OrderSys 0..* SalesOrder salesOrder: IdentitySet LineItem 0..* LineItem PersonName firstName: String lastName: String 1 OrderSys Product lineNumber: String product: Product quantity: SmallInteger salesOrder: SalesOrder Product 0..* SoftwareProduct mainPerc: float price: SmallInteger Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Object model structure 1 LineItem description: String lineItem: IdentitySet partNumber: String ServiceProduct dailyRate: SmallInteger 196 SALESORDER database tables The following Entity Relationship diagram shows the database tables that are provided on the Mapping Tool installation media and how they are joined: REPTERRITORY TERRITORY VAR SALESREP SALESORDER SALESREPEXTRA LINEITEM COMMERCIAL PRODUCT The following sections show the records that are in each sample database table and their values. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 197 Commercial The Commercial table maps to the Corporate class. The custID field is the primary key. cust ID custName cust Street custCity cust State cust Zip cust Phone territoryID 3-0921 New England Systems Maple St. Waltham MA 02186 617 555 8090 1 3-0499 Pioneer Bank Main St. Boston MA 02199 617 555 3090 1 3-2101 National Aerospace Elm St. Ann Arbor MI 00188 313 555 9882 4 3-2011 Midwest Insurance Oak St. Schaumburg IO 01234 708 555 1029 4 3-1094 Atlanta Power and Gas Pleasant St. Atlanta GA 2134 404 555 9100 3 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 198 LineItem The LineItem table maps to the LineItem class. This table has a composite primary key, composed of the fields lineOrderNo and lineNumber. lineQuantity lineOrderNo lineProductID lineNumber 3 5-669-112 O66213 1 3 5-669-112 O30991 2 22 5-671-015 W22101 1 4 5-529-778 O32889 1 3 5-529-778 O30991 2 4 5-529-778 O66213 3 1 5-709-552 W24321 1 6 5-301-881 W72101 1 6 5-301-881 W10951 2 6 5-301-881 W24321 3 3 5-301-881 W22101 4 1 5-313-003 W22101 1 1 5-313-003 W24321 2 1 5-313-003 W10951 3 5 5-719-081 O66213 1 10 5-719-081 W10951 2 3 5-331-305 O66213 1 3 5-331-305 O30991 2 22 5-431-406 W22101 1 12 5-431-406 T30119 2 12 5-431-406 T29001 3 4 5-531-507 O32889 1 3 5-531-507 O30991 2 4 5-531-507 O66213 3 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 199 lineQuantity lineOrderNo lineProductID lineNumber 4 5-531-507 C19038 4 4 5-531-507 T29001 5 1 5-631-608 W24321 1 6 5-731-709 W72101 1 6 5-731-709 W10951 2 6 5-731-709 W24321 3 3 5-731-709 W22101 4 6 5-731-709 T30119 5 1 5-831-810 W22101 1 1 5-831-810 W24321 2 1 5-831-810 W10951 3 1 5-831-810 T30119 4 1 5-831-810 T29001 5 5 5-831-810 C19038 6 5 5-931-911 O66213 1 10 5-931-911 W10951 2 5 5-931-911 C19038 3 3 5-031-012 O66213 1 3 5-031-012 W10951 2 3 5-031-012 C19038 3 3 5-031-012 T29001 4 3 5-031-012 T30119 5 8 5-131-113 O66213 1 12 5-131-113 W10951 2 5 5-131-113 C19038 3 5 5-131-113 T29001 4 5 5-131-113 T30119 5 6 5-231-214 O66213 1 10 5-231-214 W10951 2 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 200 lineQuantity lineOrderNo lineProductID lineNumber 5 5-231-214 C19038 3 1 5-341-324 O66213 1 1 5-341-324 W10951 2 1 5-341-324 C19038 3 1 5-341-324 T29001 4 1 5-341-324 T30119 5 3 5-441-434 O66213 1 3 5-441-434 W10951 2 15 5-541-544 O66213 1 10 5-541-544 W10951 2 15 5-541-544 C19038 3 15 5-131-113 T29001 4 6 5-641-654 O66213 1 1 5-641-654 W10951 2 5 5-641-654 C19038 3 1 5-641-654 T29001 4 5 5-641-654 T30119 5 5 5-741-764 O66213 1 10 5-741-764 W10951 2 5 5-741-764 C19038 3 7 5-841-874 O66213 1 7 5-841-874 W10951 2 7 5-841-874 C19038 3 5 5-941-984 O66213 1 10 5-941-984 W10951 2 5 5-941-984 C19038 3 5 5-941-984 T29001 4 5 5-941-984 T30119 5 2 5-041-394 C19038 1 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 201 lineQuantity lineOrderNo lineProductID lineNumber 2 5-141-404 O66213 1 2 5-141-404 W10951 2 2 5-141-404 C19038 3 2 5-141-404 T29001 4 6 5-241-504 O66213 1 10 5-241-504 W10951 2 6 5-241-504 C19038 3 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 202 Product The Product table maps to the ServiceProduct and SoftwareProduct classes. The prodID field is the primary key. prodID prodPrice prodMaint prodName prodType O66213 1995 .14 DataProxyForOS/2v1.0 S 72101 1295 .14 DataProxyforindosv1.0 S O30991 3995 .12 CSorkbenchforOS/2v3.5 S 10951 5995 .12 CSorkbenchforindosv3.5 S O32111 1495 .14 GroupToolforOS/2v2.0 S O32889 6995 .14 DesignareforOS/2v4.0 S 24321 4995 .12 Designareforindosv4.0 S 22101 1295 .12 GroupToolforindosv2.0 S O66011 1995 .14 DataProxyForOS/2v2.0 S 72087 1295 .12 DataProxyforindosv2.0 S O32401 3995 .14 CSorkbenchforOS/2v4.0 S 11901 5995 .12 CSorkbenchforindosv4.0 S O30801 1495 .14 GroupToolforOS/2v1.0 S O31314 6995 .14 DesignareforOS/2v3.0 S 21669 4995 .12 Designareforindosv3.0 S 20554 1295 .12 GroupToolforindosv1.0 S T30119 1600 .00 IntrotoEnfin V T29001 1600 .00 IntrotoOOAD V C19038 1200 .00 DailyConsultingRate V Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 203 RepTerritory The RepTerritory Table is the lookup table through which the SalesRep table is joined to the Territory table. You specify the RepTerritory table as the lookup table when you map the SalesRep class to the Territory table. The RepTerritory table has a composite primary key, composed of the fields territoryID and repEmployeeID. territoryID repEmployeeID 1 9004212 2 9004212 3 9004212 4 9004212 1 9001028 2 9001028 3 9001028 4 9001028 5 9001028 6 9001028 7 9001028 8 9404019 9 9404019 10 9404019 11 9404019 4 9110014 5 9110014 6 9110014 7 9309624 8 9309624 9 9309624 1 9305006 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 204 territoryID repEmployeeID 2 9305006 3 9305006 4 9305006 5 9305006 6 9305006 7 9305006 8 9305006 9 9305006 10 9305006 11 9305006 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 205 SalesOrder The SalesOrder table maps to the SalesOrder class. The orderNo field is the primary key. orderDate orderNo orderCustID orderSalesRepID 2-20-94 5-669-112 3-0921 9001028 3-02-94 5-671-015 3-0921 9404019 3-15-94 5-529-778 3-0499 9305006 4-01-94 5-709-552 3-2101 9110014 4-11-94 5-301-881 3-2011 9309624 4-11-94 5-313-003 3-2101 9110014 5-02-94 5-719-081 3-1094 9001028 1-19-94 5-331-305 3-0921 9404019 2-03-94 5-431-406 3-0499 9305006 4-13-94 5-531-507 3-0499 9001028 6-07-94 5-631-608 3-2011 9110014 5-09-94 5-731-709 3-2011 9305006 7-23-94 5-831-810 3-1094 9001028 2-03-94 5-931-911 3-2011 9404019 3-21-94 5-031-012 5-8110 9305006 4-01-94 5-131-113 5-7298 9001028 8-10-94 5-231-214 5-8110 9110014 1-11-94 5-341-324 5-1103 9001028 1-13-94 5-441-434 5-2104 9110014 2-25-94 5-541-544 5-4812 9404019 2-09-94 5-641-654 5-4812 9309624 5-10-94 5-741-764 5-4812 9001028 6-08-94 5-841-874 5-2104 9305006 4-11-94 5-941-984 5-1103 9001028 5-04-94 5-041-394 5-7298 9001028 3-09-94 5-141-404 5-7298 9309624 2-10-94 5-241-504 5-7298 9110014 Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 206 SalesRep The SalesRep table maps to the SalesRep class. The repEmployeeID field is the primary key. repEmployeeID repLastName repFirstName repPhone repStreet repCity repState repZip 9004212 Smith Joe 212555 8891 Maple St. Atlanta GA 09876 9001028 Jackson Verna 617555 4010 Elm St. Burlington MA 02166 9404019 Albertini Jack 818555 5515 Oak Ave. Hartford CO 00876 9110014 Reiner Jill 404555 1090 Tucker Rd. Miami FL 00876 9309624 Brooks Christine 214555 3390 Beacon Ave. Portland ME 00456 9305006 Thyme Justin 212555 0912 Main St. Atlanta GA 09876 SalesRepExtra The SalesRepExtra table maps to the SalesRep class. The repEmployeeID field is the primary key. repEmployeeID repSalesOffice 9004212 Chicago 9001028 Boston 9404019 Los Angeles 9110014 Atlanta 9309624 Dallas 9305006 New York Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 207 Territory The Territory table maps to the Territory class. The territoryID field is the primary key. territoryID territoryName 1 New England 2 Middle Atlantic 3 Southeast 4 Upper Midwest 5 Lower Mississippi 6 Mountain 7 Southwest 8 South California 9 North California 10 Northwest 11 Pacific Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables 208 VAR The VAR table (VAR stands for value-added reseller) maps to the VAR class. The varID field is the primary key. varStreet varZip varPhone MA 02010 617 555 8090 .35 1 Boston MA 02135 617 555 3090 .40 1 Pleasant St. Ann Arbor MI 48106 313 555 9882 .35 4 Vertical Systems Elm St. Chicago IL 60173 708 555 1029 .25 4 IXDX Fuller Rd. Atlanta GA 30328 404 555 9100 .40 3 varID varName varCity 5-8110 HighLevel Systems Maple St. Waltham 5-7298 Object Partners Co. Beacon St. 5-1103 National Software 5-2104 5-4812 varState Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: SALESORDER database tables varDiscount territoryID 209 Creating the sample application atlas You can use the sample classes provided in the SalesOrder model and the sample database tables to create an atlas and explore the features of the Mapping Tool. The following sections give an outline of how to map the sample application classes to the tables. They also list the mappings from the sample classes and their attributes to the sample database tables and their columns. Defining primary keys Before you build an atlas, you must define the primary keys in the tables. Use the information in the previous section to go into the Mapping Tool and specify the primary key for each of the tables. Mapping classes to tables Use the information given for each previous database table to map that table to the appropriate class or classes. Corporate class to Commercial table The following table shows the mapping of the Corporate class to the Commercial database table. Map attribute To field † address (D.O. ) custStreet custCity custState custZip custPhone customerID custID name custName †† salesOrder (REF ) SalesOrder Table territory (REF) Territory Table (not mapped) territoryID (join field only) † †† D.O. indicates a dependent object. REF indicates a reference attribute. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Creating the sample application atlas 210 LineItem class to LineItem table The following table shows the mapping of the LineItem class to the LineItem database table. Map attribute lineNumber To field lineNumber † product (REF ) (Product Table) quantity lineQuantity salesOrder (REF) (SalesOrder Table) (not mapped) lineOrderNo (join field only) (not mapped) lineProductID (join field only) † REF indicates a reference attribute. ServiceProduct and SoftwareProduct classes to Product table The following table shows the mapping of the ServiceProduct and SoftwareProduct classes to the Product database table. Map ServiceProduct attribute dailyRate To field prodPrice description prodName † lineItem (REF ) (LineItem Table) partNumber prodID (no equivalent) Prod-Maint (Constant Column Value = V) Prod-Type description prodName lineItem (REF) (LineItem Table) maintPerc prodMaint partNumber prodID price prodPrice (Constant Column Value = S) prodType † REF indicates a reference attribute. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Creating the sample application atlas 211 RepTerritory table The RepTerritory Table is the lookup table through which the SalesRep table is joined to the Territory table. You specify the RepTerritory table as the lookup table when you map the SalesRep class to the Territory table. This table has a composite primary key, composed of the territoryID and repEmployeeID fields. The RepTerritory table is used only to join the SalesRep and Territory tables. Therefore, you do not explicitly map it in the Mapping Tool. When you map the reference attribute in class SalesRep to the Territory table, the Mapping Tool displays the Relate Tables dialog box. You select the primary key in the SalesRep table (repEmployeeID). Then you select RepTerritory from the Lookup Table drop-down list box. To complete the join: 1. Select repEmployeeID in the lookup table. This selection joins it to the SalesRep table. 2. Select the territoryID field in the extension of the Lookup Table drop-down list box. The Mapping Tool displays the attributes of the Territory table in the Related Tables list box. 3. Select territoryID under Territory This completes the join of SalesRep to RepTerritory to Territory. 4. Click OK to exit from the dialog box. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Creating the sample application atlas 212 SalesOrder class to SalesOrder table The following table shows the mapping of the SalesOrder class to the SalesOrder database table. Map attribute † To field customer (REF ) (Commercial and VAR Tables) lineItem (REF) (LineItem Table) (not mapped) orderCustID (join field only) orderDate orderDate orderNumber orderNo orderSys (REF) (not mapped) salesRep (REF) (SalesRep and SalesRepExtra Tables) (not mapped) orderSalesRepID (join field only) † REF indicates a reference attribute. SalesRep class to SalesRep table The following table shows the mapping of the SalesRep class to the SalesRep database table. Map attribute † address (D.O. ) To field repPhone repStreet repCity repState repZip employeeID repEmployeeID personName (D.O.) repLastName repFirstName † D.O. indicates a dependent object. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Creating the sample application atlas 213 SalesRep class to SalesRepExtra table The following table shows the mapping of the SalesRep class to the SalesRepExtra database table. Map attribute To field employeeID repEmployeeID salesOffice repSalesOffice Territory class to Territory table The following table shows the mapping of the Territory class to the Territory database table. Map attribute To field † customer (REF ) (Commercial and VAR Tables) salesRep (REF) (SalesRep Table) territoryID territoryID territoryName territoryName † REF indicates a reference attribute. VAR table The following table shows the mapping of the VAR class to the VAR database table. Map attribute To field address (D.O.†) varStreet varCity varState varZip varPhone customerID varID discountRate varDiscount name (D.O.) varName territory-ID †† salesOrder (REF ) (SalesOrder Table) territory (REF) (Territory Table) † †† D.O. indicates a dependent object. REF indicates a reference attribute. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Creating the sample application atlas 214 Defining dependent objects After you have mapped the primitive attributes in each class, use the previous information to define the dependent objects in each class, and map their attributes to the appropriate table fields. Mapping reference attributes After you have mapped both the primitive attributes and the dependent objects in all classes, map the reference attributes in each class. These mappings specify how objects are related and allow the Mapping Tool to retrieve both an object and its related objects from the database. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Sales Order application Section: Creating the sample application atlas 215 B CarSale tutorial Before you begin Before you can use the CarSale tutorial, the UniSQL 3.5.3 client software must be installed, and you must have access to the UniSQL demodb database. In addition, the following applications must be loaded in ObjectStudio: ♦ Modeling Tool ♦ UniSQL POF ♦ UniSQL Schema Generator After loading these applications, begin the CarSale tutorial by performing the steps in “Creating a database schema” on page 219. To successfully complete this tutorial, you should have a basic knowledge of ObjectStudio, the Modeling Tool, and a UniSQL Server database. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Before you begin 216 Tutorial description This tutorial is based on the carSale model. The CarSale tutorial provides an overview on how to implement a UniSQL schema and map a UniSQL schema to an ObjectStudio class hierarchy. The CarSale tutorial demonstrates how to: ♦ Create a database schema ♦ Create Smalltalk classes from the CarSale model ♦ Map a database schema to an object hierarchy ♦ Log on to the database ♦ Create an object instance ♦ Retrieve information from the database ♦ Log off the database This tutorial provides a business model that includes the classes, methods, and attributes required to demonstrate how to use ObjectStudio with a UniSQL Server database. When developing your applications, however, the preliminary steps include analyzing your business needs, designing and building a model that represents your system structure, and creating a user interface. For information about using the Modeling Tool, refer to the ObjectStudio Modeling Tool User’s Guide, P40-3111. Scenario The CarSale tutorial is based on the following scenario: A car retail company sells several car models. Each model can be purchased with a specific set of options, such as power windows, leather seats, a CD player, or a cellular phone. Each option is available for one or more models, and every car sold is equipped with zero or more options. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Tutorial description 217 The following diagram illustrates the business model for the CarSale tutorial: CarModel 1+ CarSale CarModel CarSale CarModel CarOption CarSale CarOption PricedOption Tire CarOption PaintJob Others Stereo Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Tutorial description 218 Creating a database schema After designing a business model, you can create a database schema: 1. Open the Modeling Tool, and load the CarSale model (POFST\POF\CarSale\Carsale.mod). 2. Open the Schema Generator and select all classes as shown: 3. Enter a file name. 4. Click Generate. 5. Click Visual SQL to access a UniSQL database and open UniSQL’s Visual SQL editor. 6. Enter a database name, a user name, and a password. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Creating a database schema 219 7. Click Open. A window with the DDL for carSale is opened as shown: From this window: A. Resolve keyword conflicts by changing all occurrences of Others to otherOptions (Others is a restricted name in UniSQL). B. Change the attribute name order to orderno (order is a restricted name in UniSQL). C. Select Transaction ⇒ Run from the menu bar, or click Run to run the SQL script. D. Select Transaction ⇒ Commit from the menu bar to commit changes to the database. E. Save the file. F. Close Visual SQL. When you complete these steps, the database contains your schema, and you can perform the steps in “Creating Smalltalk classes.” Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Creating a database schema 220 Creating Smalltalk classes After performing the steps in “Creating a database schema,” create Smalltalk classes from the CarSale model: 1. Select Tools ⇒ Synchronization implementation from the menu bar. A form displays as shown: 2. Select all classes in the All model classes list. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Creating Smalltalk classes 221 3. Click More. The property page displays as shown: 4. Set Class file root directory. 5. Select the Synchronization tab. The property page displays as shown: 6. Set the default superclass to PersistentObject. 7. Click OK. The Synchronize implementation form appears. 8. Click Synchronize. A progression bar indicates synchronization of the database schema and ObjectStudio. Once the Smalltalk classes are generated, you can use this model from ObjectStudio. Next, perform the steps listed in the next section, “Mapping a database schema to an object hierarchy.” Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Creating Smalltalk classes 222 Mapping a database schema to an object hierarchy After creating the database schema and Smalltalk classes, create a map for the business model: 1. Open the Class Browser. 2. Select UFSmalltalkToDatabaseMaps from the list. 3. Select Class ⇒ New from the menu bar to create a subclass of UFSmalltalkToDatabaseMaps. The Class Definition dialog box appears as shown: 4. Verify that UFSmalltalkToDatabaseMaps is the superclass and then enter CarMap as the class name. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Mapping a database schema to an object hierarchy 223 5. Click OK. The following dialog box appears: 6. Enter CarMap.cls in the file name field, and click Save. The Class Browser appears as shown: 7. Select the subclass CarMap; then click the Class radio button to create a class method named initialize. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Mapping a database schema to an object hierarchy 224 8. Select Method ⇒ New from the menu bar; then enter the following in the source window: initialize 9. To resolve class name conflicts, enter the following code to map Others to otherOptions in the initialize method: "*** Others ***" | aMap anAttribute | aMap := UFClassMap new. aMap databaseName: #otherOptions; smalltalkName: #Others. SmalltalkToDatabaseMaps addMap: aMap. 10. To resolve attribute name conflicts, enter the following code to map the attribute order to orderno: "*** carSale ***" aMap := UFClassMap new. aMap databaseName: #carsale; smalltalkName: #CarSale. anAttribute := UFAttributeToColumnMap new. anAttribute databaseName: #orderno; smalltalkName: #order. aMap userDefinedPersistentAttributeMapsAdd: anAttribute. SmalltalkToDatabaseMaps addMap: aMap. 11. Enter the following code to map the data type conversion for the attribute hasAirbag from Boolean to char(3): "*** carModel ***" aMap := UFClassMap new. aMap databaseName: #carmodel; smalltalkName: #CarModel. anAttribute := UFAttributeToColumnMap new. anAttribute databaseName: #hasAirbag; smalltalkName: #hasAirbag; inConvertMethod: #asUniSQLBoolean; outConvertMethod: #asUniSQLString. aMap userDefinedPersistentAttributeMapsAdd: anAttribute. SmalltalkToDatabaseMaps addMap: aMap. 12. Select Method ⇒ Save from the menu bar. Next, follow the steps in “Logging on to the database.” Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Mapping a database schema to an object hierarchy 225 Logging on to the database To log on to the database, open the workspace and enter the following code: [ UFDatabase logon: #<your userid> password: #<your password>' database: #<your database>. ] on: POFUFLogonError do: [ :exp | exp inspect]. If the logon fails, an inspector window is displayed. To see the error description, check the description variable. If the logon is successful, the objects are accessible. Next, follow the steps in “Creating an object instance.” Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Logging on to the database 226 Creating an object instance To create an instance of CarModel with specific options, open the workspace and execute the following code: Model := CarModel new. Model name: 'VW Golf'. Model price: 20000. T := Tire new. T name: 'gold extra deLux'. T price: 9.99. O := Others new. O description: 'Leather seats'. Model carOptionInsert: T. Model carOptionInsert: O. To save these instances to the database, execute the following code: Model saveAll. To save the structure with your own error handling and transaction management, execute the following code: [ TransactionManager begin. Model saveAll. TransactionManager commit. ] on: Exception do: [ :error | [ TransactionManager rollback ] on: Exception do: [ :exp | nil ]. error inspect. ]. If an error occurs, the transaction is rolled back (the default behavior of the saveAll method), and an inspector window displays the error exception object. To determine the error, check the description attribute of this object. To change an object attribute, execute the following code: O name: 'seat'. O save. Next, perform the steps in “Retrieving information from the database.” Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Creating an object instance 227 Retrieving information from the database To retrieve a collection of all car models, execute: CarModel findAll inspect. An inspector window opens with an array containing one instance of CarModel. Traverse the instance attributes to find the previously inserted CarOptions. To search for specific information, execute: (CarOption findWhere: 'name = ''seat''') inspect. An array contains one instance of Others. To check for the POFNotFound condition, execute: [ Co := CarOption findWhere: 'name = ''Door'''. ] on: POFNotFound do: [ :exp | exp exString inspect ]. The inspector window displays Row not found. Next, perform the steps in “Logging off from the database.” Logging off from the database To log off from the database, execute: UFDatabase logoff. This completes the CarSale tutorial. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: CarSale tutorial Section: Retrieving information from the database 228 C Paradise demo Before you begin Before you can use the Paradise demo, the UniSQL client software must be installed, and you must have access to the UniSQL demodb database. UniSQL POF must also be loaded in ObjectStudio; then you can load the Paradise demo. Application description The sample application that uses Smalltalk to retrieve and manipulate database objects is the Paradise Vacation Planner. This application allows agents at the Paradise Travel Agency to retrieve accommodations from the database (all accommodations or selected ones); add accommodations to and delete accommodations from the database; and update accommodation details such as rates, checkout times, and activities. The Accommodations class is set up for inheritance purposes only; it has no instances and only four subclasses: Resort, Hotel, Motel, and BedAndBreakfast. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Before you begin 229 The following diagram illustrates the business model for the Paradise demo: ParadiseAppCtr Accommodations ParadiseAppCtr PictureDemo 1+ Rooms Accommodations PictureDemo Accommodations Quarters Accommodations Eatery Meal Eatery 1+ Cabin Meal Resort BedAndBreakfast Meal BedAndBreakfast Hotel Motel Resort Cabin SeaShore Resort SeaShore The following information shows the graphical interface for the Paradise demo application and how methods and attributes are used to retrieve and update data. Before binding code to the interface components, instance variables were defined to store objects. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Application description 230 Loading the Paradise demo To load the Paradise demo from the ObjectStudio Work Area: 1. Select File ⇒ Load application from the menu bar. 2. Click Load text. 3. Select PARADISE.TXT from the POFST\POF directory. An icon is displayed in the Work Area. 4. Double-click the Paradise icon. The dialog box appears as shown: 5. Enter the required information, and click the screen icon to log on and display the main form. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Loading the Paradise demo 231 The following table lists the methods used when logging on: Item Database User Name Description Method implementation The database to which you want to connect. Set the database name, such as: Your user name. Set the user name, such as: dbname := efDBName getValue. user := efUserName getValue. Password Your security password. Set the password, such as: pass := efPassword getValue. The following example shows the events that occur when you log on: doLogon | dbname pass user | self displayStatus: 'Logging in to the database'. dbname := efDBName getValue . pass := efPassword getValue. user := efUserName getValue. loginForm close. [ subject doLogon: dbname password: pass username: user. queryClassName := #Accommodations. queryWhereCondition :=''. querySortMethod := #Unsorted. self queryChanged. lbAccommodations setSelectionTo: 1. self displayStatus: 'Ready'. ] on: Exception do: [ :ex | ^ModalMessageBox title: 'Login Error' text:( ex exString ++' Would you like to retry?') icon: #StopSign buttons: { #Yes #No } action: #retryIf: controller: self. ]. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Loading the Paradise demo 232 Main form. The main form demonstrates how to: ♦ Add an instance of Accommodations ♦ Delete the selected instance ♦ Select specific instances ♦ Set instance attributes ♦ Save instance attributes Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Loading the Paradise demo 233 The following table describes the interface items: Item Description Method implementation Accommodations List the instances of the Accommodations class. Use #findAll or one of the #findWhere: methods. Add Add an instance. Use #pbAddAccommodationClicked. Delete Delete the selected instance. Use #pbDeleteClickedAction:. Select Select all instances that meet specific criteria. Use #pbSelOKClicked. Details Display more information about the selected instance. Use #pbDetailsClicked. Exit Close the application. Use #close. To add an instance of the Accommodations class, click Add and follow the instructions in “Adding an instance” on page 235. The following example shows the events that occur when you select an accommodation from the list and click Details: pbDetailsClicked " This method will be called when the 'clicked' event is triggered by the 'pbDetails (Button)' object. " selectedAccommodation := subject accommodations at: lbAccommodations getSelection. self openDetailsSheet. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Loading the Paradise demo 234 Adding an instance When you click Add on the main form, the following form displays: The Accommodations class has four subclasses: Resort, Hotel, Motel, and BedAndBreakfast. Each subclass represents a type of accommodation. To add an instance: 1. Select the radio button for the type of accommodation you want to add. 2. Enter the proper information in the required fields, and click OK. The following table describes the interface items: Item Type of Accommodation Description Accommodation type: Resort, Hotel, Motel, Bed and Breakfast. Method implementation Set the accommodation type, such as: rbAddAccType getValue. Name Accommodation name. Set the name attribute, such as: selectedAccommodation name: efAddAccName getValue. Country Country in which the accommodation is located. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Adding an instance Set the country attribute, such as: selectedAccommodation country: efAddAccCountry getValue. 235 After adding an instance, the Details property sheet is displayed for changing values (attributes) for the selected accommodation. For specific instructions, see “Setting instance attributes” on page 243. The following example shows the events that occur when you select an accommodation type, enter a name and country, and click OK to add a new accommodation to the database: pbAddAccOKClicked " This method will be called when the 'clicked' event is triggered by the 'pbAddAccOK (Button)' object. " (efAddAccName getValue) isEmpty ifFalse: [ selectedAccommodation := (System at: (rbAddAccType getValue asSymbol) ) new. selectedAccommodation name: efAddAccName getValue. selectedAccommodation country: efAddAccCountry getValue . addAccForm close. self saveAccommodation. self openDetailsSheet. self queryChanged. ] ifTrue: [ ModalMessageBox title: 'Adding New Accommodation' text: 'Accommodation Name is Empty' icon: #StopSign buttons: { #Yes } action: #queryError: controller: self. ]. To save the new instance, enter the following code: saveAccommodation: accommodation accommodation save. self accommodationsInsert: accommodation. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Adding an instance 236 Deleting an instance To delete an instance of the Accommodations class: 1. Select an instance from the list of accommodations on the main form. 2. Click Delete. The following example shows the events that occur when you delete an instance from the database: The message box to confirm the delete operation pbDeleteClicked " This method will be called when the 'clicked' event is triggered by the 'pbDelete (Button)' object. " | value | value := lbAccommodations getValue. ModalMessageBox title: 'Delete Record' text: 'Are you sure you want to delete' ++'"' + value + '"' icon: #QuestionMark buttons: { #Yes #No } action: #pbDeleteClickedAction: controller: self. To delete an instance of accommodation from the database: deleteAccommodation: accommodation | acc accd | acc := accommodations at: accommodation. accd := accommodations at: accommodation. accd delete. " Delete an accommodation from DB" self accommodationsRemove: acc Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Deleting an instance 237 Selecting specific instances You can specify which instances you want to retrieve from the database by clicking Select on the main form. The following dialog box appears: Choose the selection criteria as appropriate; then click OK. The accommodations that match the selection criteria are displayed on the main form. The following table describes the interface items: Item Selected Accommodations Unsorted Description Method implementation Restrict the search to a specific accommodation type or all accommodations that match certain criteria. Use #findAll, such as: Search for all accommodation subclasses and do not sort. Use #findAll or #findLimit:, such as: Hotel findAll. Resort findAll. Hotel findAll. Resort findAll. Sorted By Name Search for all accommodation subclasses and sort by name. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Selecting specific instances Use #findAllOrderBy:, such as: Resort findAllOrderBy: 'name ASC'. 238 Item Description Method implementation Sorted By Cost Search for all accommodation subclasses and sort by cost. Use #findAllOrderBy:, such as: Hotel Search for all occurrences of the subclass, Hotel. Use #findAll, such as: Search for all occurrences of the subclass, Motel. Use #findAll, such as: Search for all occurrences of the subclass, Resort. Use #findAll, such as: BedAndBreak fast Search for all occurrences of the subclass, BedAndBreakfast. Use #findAll, such as: Country Search for all accommodations or occurrences of the selected accommodation type in the specified country. Use #findWhere:, such as: Search for all accommodations, or occurrences of the selected accommodation type where the maximum cost does not exceed the specified amount. Use #findWhere:, such as: Search for all accommodations or occurrences of the selected accommodation type that have a pool. Use #findWhere:, such as: Motel Resort Max Cost Has Pool Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Selecting specific instances Resort findAllOrderBy: 'cost'. Hotel findAll. Motel findAll. Resort findAll. BedAndBreakfast findAll. Accommodations findWhere: 'country = "Jamaica"' . Accommodations findWhere: 'cost < 100'. Accommodations findWhere: 'numberOfPools > 0'. 239 The following example shows the events that occur when you search for all motels in France that have a pool. The final request to retrieve all motels will be: Motel findWhere: 'country = ''France'' and numberOfPools > 0'. This query is supported by the following code: pbSelOKClicked " This method will be called when the 'clicked' event is triggered by the 'pbSelOK (Button)' object. " queryWhereCondition := ''. queryClassName := #Accommodations. querySortMethod := rgSortOrder getValue. cbSelSelectAccommodations getValue ifTrue: [ cbSelAll getValue ifFalse: [ queryClassName := rgAccommodationType getValue. ]. "Build selection criteria " "Assign a valid 'Where' clause to the query variable " "queryWhereCondition' to retrieve necessary data. " efSelCountry getValue = '' ifFalse: [ queryWhereCondition := queryWhereCondition ++ 'country =' ++ '''' + efSelCountry getValue + ''''. ]. nfSelCost getValue > 0 ifTrue: [ queryWhereCondition := '' ifTrue: [ queryWhereCondition := queryWhereCondition ++ 'and'. ]. queryWhereCondition := queryWhereCondition ++ 'cost <=' ++ nfSelCost getValue. ]. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Selecting specific instances 240 cbSelHasPool getValue ifTrue: [ queryWhereCondition := '' ifTrue: [ queryWhereCondition := queryWhereCondition ++ 'and'. ]. queryWhereCondition := queryWhereCondition ++ 'number_of_pools > 0'. ]. ]. rgSortOrder enable. selectionCriteriaForm close. self queryChanged. queryChanged self displayStatus: 'Database query'. [ subject retrieveAccommodations: queryClassName sortMethod: querySortMethod whereCondition: queryWhereCondition. self reloadAccommodationsListbox. ] on: Exception do: [ :ex | ModalMessageBox title: 'Query Error' text: ex exString icon: #StopSign buttons: { #Yes } action: #queryError: controller: self. ]. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Selecting specific instances 241 retrieveAccommodations: aClassName sortMethod: aMethod whereCondition: whereString | result queryClass | (queryClass := System at: aClassName) notNil ifTrue: [ (aMethod isNil or: [aMethod asString = 'Unsorted']) ifTrue: [ (whereString isNil or: [whereString isEmpty]) ifTrue: [ result := queryClass findAll ] ifFalse: [ result := queryClass findWhere: whereString ]. ] ifFalse: [ (whereString isNil or: [whereString isEmpty]) ifTrue: [ result := queryClass findAllOrderBy: aMethod ] ifFalse: [ result := queryClass findWhere: whereString orderBy: aMethod ]. ]. accommodations := result. accNames := accommodations collect: [ :each | each name ]. ]. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Selecting specific instances 242 Setting instance attributes When you add a new instance to the database or select one from the main form and click Details, a property sheet appears as shown: Use this dialog box to set or update the attributes for an accommodation’s location, rates, facilities, activities, restrictions, and room descriptions. The Activities tab is available only if Resort is chosen as the accommodation type. After setting instance attributes and clicking OK, the main form appears. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 243 Location The Location tab (illustrated in “Setting instance attributes,” beginning on page 243) provides the ability to change attributes for the currently selected accommodation. Enter or update the information as appropriate; then select another tab or click OK. The following table describes the interface items: Item Name Description Accommodation name. Method implementation Set the name attribute, such as: selectedAccommodation name: efAccName getValue. Country Type of Accommodation Country in which the accommodation is located. Set the country attribute, such as: The class type: Resort, Hotel, Motel, or BedAndBreakfast. Display the class type for the current accommodation, such as: Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes selectedAccommodation country: efAccCountry getValue. rbAccType setSelectionTo: selectedAccommodation class name. 244 Rates The Rates tab provides the ability to change instance attributes as illustrated in the following example: Enter or update the information as appropriate; then select another tab or click OK. The following table describes the interface items: Item Cost Description Accommodation cost. Method implementation Set the cost attribute, such as: selectedAccommodation cost: efCost getValue asDecimal. Checkout Time occupant must check out of the room. Set the checkoutTime attribute, such as: selectedAccommodation checkoutTime: efCheckoutTime getValue asTime. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 245 Facilities The Facilities tab provides the ability to change instance attributes as illustrated in the following example: Enter or update the information as appropriate; then select another tab or click OK. The following table describes the interface items: Item Restaurants Description Number of restaurants. Method implementation Set the numberOfRestaurants attribute, such as: selectedAccommodation numberOfRestaurants: efNoOfRestaurants getValue. Pools Number of pools. Set the numberOfPools attribute, such as: selectedAccommodation numberOfPools: efNoOfPools getValue. Beach The accommodation does or does not have a beach. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes N/A 246 Restrictions The Restriction tab provides the ability to change instance attributes as illustrated in the following example: Enter or update the information as appropriate, then select another tab or click OK. The following table describes the interface items: Item Allows Children Description Whether the accommodation allows children or not. Method implementation Set the allowsChildren attribute, such as: selectedAccommodation allowsChildren: cbAllowsChildren getValue. Allows Pets Whether the accommodation (motels only) allows pets or not. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes Set the allowsPets attribute, such as: selectedAccommodation allowsPets: cbAllowsPets getValue. 247 Activities The Activities tab provides the ability to change instance attributes as illustrated in the following example: The Activities tab is available only if Resort is chosen as the accommodation type. Enter or update the information as appropriate; then select another tab or click OK. The following table describes the interface items: Item Description Method implementation Activity List of activities available for the current accommodation. Use #openActivitiesPage. New Enable the ability to add a new activity. Use #pbNewActivityClicked. Delete Delete the selected activity from the list. Use #pbDeleteActivityClicked. Enter a new activity Name of the activity to add to the list. Use #pbNewActivityClicked. Add Insert the new activity, and add it to the list. Use #pbAddActivityClicked. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 248 Adding an activity Select the Activities tab on the Details property sheet to add an activity to the current class instance. Then: 1. Click New. 2. Enter a description in the edit box. 3. Click Add. The new activity is displayed in the list. The following example shows the events that occur when you add an activity: pbNewActivityClicked " This method will be called when the 'clicked' event is triggered by the 'pbNewActivity (Button)' object. " self enableAddActivity. pbAddActivityClicked " This method will be called when the 'clicked' event is triggered by the 'pbAddActivity (Button)' object. " | activity | activity := efActivityToAdd getValue. activity isEmpty ifFalse: [ (selectedAccommodation activities == nil) ifTrue: [ selectedAccommodation activities: (Set new). ]. selectedAccommodation activities add: activity. ]. self activitiesChanged. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 249 Deleting an activity Select the Activities tab on the Details property sheet to delete an activity from the current class instance. Then: 1. Select an activity from the list. 2. Click Delete. The activity is deleted from the list. The following example shows the events that occur when you delete an activity: pbDeleteActivityClicked " This method will be called when the 'clicked' event is triggered by the 'pbDeleteActivity (Button)' object. " | activities selectedActivities | lbAccActivities getSelection :: 0 ifTrue: [ activities := lbAccActivities getList. activities removeAt: lbAccActivities getSelection. selectedAccommodation activities: activities. ]. self activitiesChanged. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 250 Rooms The Rooms tab provides the ability to change instance attributes as illustrated in the following example: Use this property page to: ♦ Add a room ♦ Delete a room ♦ View detailed information (attributes) about the currently selected type of room Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 251 The following table describes the interface items: Item Description Method implementation Rooms List of rooms available for the current accommodation. Use #openRoomsPage. Suite Type of room. Set the type of room as Suite. Cabin Type of room. Set the type of room as Cabin. PrivateRoom Type of room. Set the type of room as PrivateRoom. New Enable the ability to add a new room. Use #pbRoomsNewClicked. Delete Delete the selected room from the list. Use #pbRoomsDeleteClicked. Details Display the room attributes for the selected room. Use #pbRoomDetailsOKClicked. Add Add a room for the current accommodation. Use #pbRoomsAddClicked. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 252 Adding a room Select the Rooms tab on the Details property sheet to add a room to the current class instance. Then: 1. Select the appropriate room type (suite, cabin, private room). 2. Click New. 3. Click Add. A dialog box appears for setting attributes, as shown here: 4. Enter information as appropriate 5. Click OK. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 253 The following table describes the interface items: Item Description Size in sq. ft. Room size. Method implementation Set the sizeInSqFt attribute. newRoom sizeInSqFt: efRoomSize getValue. Has view of View from the room. Set the hasViewOf attribute. newRoom hasViewOf: efRoomView getValue. Bed description Type of bed. Set the bedDescription attribute. newRoom bedDescription: efRoomBedDescr getValue. Bath description Type of bath. Set the bathDescription attribute. newRoom bathDescription: efRoomBathDescr getValue. The following example shows the events that occur when you add a room: pbRoomsAddClicked " This method will be called when the 'clicked' event is triggered by the 'pbRoomsAdd (Button)' object. " | room | room := (System at:(rbRoomsType getValue asSymbol)) self saveRoom: room. selectedAccommodation roomsInsert: room. self reloadRoomsList. lbAccRooms setSelectionTo: lbAccRooms getList size. self openRoomsDetails: room. self enableRoomsControls. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes new. 254 Deleting a room Select the Rooms tab on the Details property sheet to delete a room from the current class instance. Then: 1. Select a room from the list. 2. Click Delete. The following example shows the events that occur when you delete a room: pbRoomsDeleteClicked " This method will be called when the 'clicked' event is triggered by the 'pbRoomsDelete (Button)' object. " | room | room := self retrieveRoom: lbAccRooms getSelection. self deleteRoom: room. selectedAccommodation roomsRemove: room. self reloadRoomsList. self enableRoomsControls. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 255 Viewing room details Select the Rooms tab on the Details property sheet to see detailed information (attributes) about a specific room. Then: 1. Select a room from the list. 2. Click Details. A dialog box displays the room’s current attributes. For a description of the interface items, see “Adding a room” on page 253. The following example shows the events that occur when you select a room and click Details: pbRoomsDetailsClicked " This method will be called when the 'clicked' event is triggered by the 'pbRoomsDetails (Button)' object. " self openRoomsDetails: ( self retrieveRoom: getSelection). lbAccRooms To save the attribute values for the currently selected accommodation, follow the instructions in “Saving instance attributes.” Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Setting instance attributes 256 Saving instance attributes To save the attribute values entered on the Location, Rates, Activities, and Rooms pages, click OK on the Details form. The following example shows the events that occur: detailsSheetOnOK " This method will be called when the 'onOK' event is triggered by the 'DetailsSheet (Form)' object. " selectedAccommodation name: efAccName getValue. selectedAccommodation country: efAccCountry getValue. selectedAccommodation cost: efCost getValue asDecimal. selectedAccommodation checkoutTime: efCheckoutTime getValue asTime. selectedAccommodation numberOfPools: efNoOfPools getValue. selectedAccommodation numberOfRestaurants: efNoOfRestaurants getValue. selectedAccommodation allowsChildren: cbAllowsChildren getValue. selectedAccommodation class name = #Motel ifTrue: [ selectedAccommodation allowsPets: cbAllowsPets getValue. ]. detailsSheetForm close. self saveAccommodation. self queryChanged. lbAccommodations setFocus. This concludes the Paradise demo. Persistent Object FrameWork User's Guide, P40-3222-02 Chapter: Paradise demo Section: Saving instance attributes 257 Index A Abstract framework 29 abstract superclasses definition 16 gen-spec relationships 147, 150 access layer 21 activate, Benchmark class method 86 addArrayOfData:, Benchmark class method 86 addData:, Benchmark class method 87 adding to atlas classes 119 tables 123 administration, Relational POF 176 aggregation, definition 15 applications development overview 179 loading 100 named Benchmark 82 Modeling Base 82 sample 183, 195 architecture, application 18 association, definition 14 Persistent Object FrameWork User's Guide, P40-3222-02 Index atlases adding classes 118, 119 tables 123 closing 134 creating 117 default saving 160 defining save settings 163 deleting 134 editing 131 loading multiple 113 mapping reports 166 opening 130 preferences 115 removing classes 131 tables 131 renaming 132 saving 159 setting preferences 115 specifying associated databases 117 steps for building 114 synchronizing 133 testing maps 172 attribute maps 142 258 attributes changing names (UniSQL example) 220 data-type conversion example 225 requirement 186 definition 12 mapping example 225 mapping reports 166 Mapping Tool icon 108 reference, mapping 144 setting CarSale tutorial, example 227 Paradise demo, example 243 B begin, transaction manager instance method 62 begin:, Benchmark class method 87 begin:with:, Benchmark class method 87 begin:with:with:, Benchmark class method 88 begin:with:with:with:, Benchmark class method 88 begin:with:with:with:with:, Benchmark class method 88 Persistent Object FrameWork User's Guide, P40-3222-02 Index Benchmark class description 86 methods activate 86 addArrayOfData: 86 addData: 87 begin: 87 begin:with: 87 begin:with:with: 88 begin:with:with:with: 88 begin:with:with:with:with : 88 deactivate 88 end 88 endWith: 88 endWith:with: 88 endWith:with:with: 88 isActive 89 isActive: 89 observations 89 reset 89 time 89 Benchmark Explorer 82 benchmarking activating 84, 86 adding data 87 adding data array 86 asking state 89 beginning new 87, 88 calculating time 89 deactivating 84, 88 ending 88 initiating 82 refreshing 85 resetting 84, 89 returning observations 89 setting state 89 Benchmarking framework 82, 83 brokers, request 32, 65 business layer 20 business models 20 business objects 20 259 C CarSale tutorial creating database schema 219 instance 227 description 183 loading 216 overview 217 retrieving information 228 saving an instance 227 setting object attribute 227 child classes 16 Class Browser, creating a map class example 224 procedure 187 class maps creating demo example 223, 224, 225 UniSQL POF 187, 188 definition 141 loading, UniSQL POF 182 Persistent Object FrameWork User's Guide, P40-3222-02 Index classes adding to atlas 118, 119 Benchmark 86 creating 97 definition 13 dependent 156 in Abstract framework 29 in Relational framework 30 in UniSQL framework 31 loading 102 mapping reports 166 Mapping Tool icon 108 moving into Developer 20 persistent 169 POF exceptions 189 POF-specific DynamicPersistencyBroker 34 MFAtlas 129 MFBroker 34 MFConcurrencyManager 129 MFDatabase 34 MFSQLBroker 34 MFSQLGenSpecBroker 34 PersistencyBroker 35 PersistencyBrokerManager 35 PersistencyRequestBroker 35 PersistentObject 35 PersistentObjectPool 35 PersistentStore 36 ScrollableObjectCursor 36 TransactionManager 36 UFBroker 36 UFDatabase 36 preparing 98 removing from atlases 131 request brokers 32, 65 Smalltalk, generating 182, 221 synchronizing definition 182 example 221 260 close, ObjectCursor instance method 58 collapsed gen-spec maps 147 collection, retrieving, example 228 column editor 124, 126, 127 columns definition 25 mapping reports 166 Mapping Tool icon 109 commit point 72 commit, transaction manager instance method 62 concurrency management 99, 126, 129 concurrent access 33 current, ObjectCursor instance method 58 cursors object 32 positioning 60, 61 scrollable object 32 services closing 58 opening 59 positioning 59 returning current 58 returning size 61 Persistent Object FrameWork User's Guide, P40-3222-02 Index D databases associating with atlas 117 associations, changing 132 concurrent access 33 connecting with a database 184 database schema, creating 219, 220 database theory, suggested reading 23, 24, 26 definition 23 disconnecting from a database 184 logon example 231 qualifiers 113 support, loading 100 types object 24 relational 25 data-retrieval services. See object-retrieval services deactivate, Benchmark class method 88 debugging proxies 116 default mapping, inverse attributes 116 delete activity example 250 delete, PersistentObject instance method 54 deleting objects 169 261 demo applications CarSale tutorial creating database schema 219 creating instance 227 description 217 retrieving information 228 saving an instance 227 setting object attribute 227 Paradise Vacation Planner adding an instance 235 deleting an instance 237 description 183 loading 231 main form 233, 234 overview 229 selecting specific instances 238 setting instance attributes 243 dependent object example 195 maps 156 Designer, ObjectStudio 19 destructive transformation 77 development environment 19 disable, PersistentObjectPool instance method 63 domains, loading 102 DynamicPersistencyBroker class 34 Persistent Object FrameWork User's Guide, P40-3222-02 Index E enable, PersistentObjectPool instance method 63 encapsulation 13 end, Benchmark class method 88 endWith:, Benchmark class method 88 endWith:with:, Benchmark class method 88 endWith:with:with:, Benchmark class method 88 errors handling example 227 POF exceptions 189 exception classes, POF 189 explorer, Benchmark 82 F find, PersistentObject instance method 50 findAll:, PersistentObject class method 39 findAllLimit:, PersistentObject class methods 39 findAllOrderBy:, PersistentObject class method 39 262 findAllOrderBy:limit:, PersistentObject class method 40 findLimit:, PersistentObject instance method 50 findOrderBy:, PersistentObject instance method 50 findOrderBy:limit:, PersistentObject instance method 51 findQuery:, PersistentObject class method 40 findQuery:limit:, PersistentObject class method 41 findWhere:, PersistentObject class method 41 findWhere:limit:, PersistentObject class method 42 findWhere:orderBy:, PersistentObject class method 42 findWhere:orderBy:limit:, PersistentObject class method 42 first, ScrollableObjectCursor instance method 60 flush, PersistentObjectPool instance method 63 flushForClass:, PersistentObjectPool instance method 64 flushForObject:, PersistentObjectPool instance method 64 foreign key definition 25 Mapping Tool icon 109 using in joins 138 frameworks Abstract 29 definition of 28 Relational 30 UniSQL 31 Persistent Object FrameWork User's Guide, P40-3222-02 Index G generating reports 168 gen-spec definition of 16 map 147, 150 Mapping Tool 118 I icons, Mapping Tool 100 images, saving 101 inheritance among classes 16 gen-spec relationships 147, 150 inherited gen-spec maps 150 initialize method example 224 initializeInstanceVariables, PersistentObjectPool instance method 64 install requirements, Mapping Tool 93 installation Mapping Tool 93 related documentation, Mapping Tool 93 instance definition 13 examples adding 235 changing an attribute 227 creating 227 deleting 237, 255 retrieving 228 saving 227 setting attributes 235, 236, 243 sort criteria 238 viewing attributes 232, 234 instance variables initializing 64 transactionLevel 62 interface to databases 21 isActive, Benchmark class method 89 263 isActive, PersistentObjectPool instance method 64 isActive:, Benchmark class method 89 isActive:, PersistentObjectPool instance method 64 isObjectCursor, ObjectCursor instance method 58 isOpen, ObjectCursor instance method 58 isPersistent, PersistentObject instance method 56 isPersistentObject, PersistentObject instance method 56 isScrollableObjectCursor, ScrollableObjectCursor instance method 60 J joins between tables 138 creating 145 definition 25 lookup table 155 specifying 146 K keys definition 25 foreign 109 primary 169 using in joins 138 keywords, resolving conflicts (UniSQL example) 220 Persistent Object FrameWork User's Guide, P40-3222-02 Index L last, ScrollableObjectCursor instance method 60 layers access 21 business 20 view 19 loading CarSale model 219 CarSale tutorial 216 database support 100 maps, UniSQL POF 182 Paradise demo 231 Sales Order application 105 locking types 33 logging off database 184 logging on database 184 lookup table maps 152 M managing concurrency 126 many-to-many relationships 14 mapping basics 135 between objects and relational tables 27 reports 166 UniSQL example attributes 225 data types 225 database schema 223 UniSQL POF creating a map class 187, 188 support 178 UFSmalltalkToDatabaseMa ps class 185 mapping reports, contents 166 264 Mapping Tool description 92 Desktop icon 100 icons class and attribute 108 table and column 109 list boxes atlases 108 Mapped Attributes 110 Mapped Classes 110 Mapped Columns 110 Mapped Tables 110 Related Classes 110 Related Tables 110 loading 100 main window 106 menus 111 opening 105 saving image 101 steps for using 96 toolbar 112 uninstalling 95 maps attribute 142 class 141 collapsed gen-spec 147 creating demo example 223 UniSQL POF 187, 188 data types 225 dependent object 156 inherited gen-spec 150 joining tables 145 loading, UniSQL POF 182 lookup table 152 order 137 partitioned class 150 reference attribute 144 relationships 144 testing 172 types 135, 141 UniSQL POF creating 187, 188 referencing 185 MAPTOOL.INI file 176 menus, Mapping Tool 111 Persistent Object FrameWork User's Guide, P40-3222-02 Index methods Benchmark class activate 86 addArrayOfData: 86 addData: 87 begin: 87 begin:with: 87 begin:with:with: 88 begin:with:with:with: 88 begin:with:with:with:with : 88 deactivate 88 end 88 endWith: 88 endWith:with: 88 endWith:with:with: 88 isActive 89 isActive: 89 observations 89 reset 89 time 89 definition 12 generating 163, 165 generating workplace objects 165 including in model file 163, 165 notifying when changed 163, 165 ObjectCursor instance close 58 current 58 isObjectCursor 58 isOpen 58 next 59 open 59 position 59 265 methods (cont.) PersistentObject class findAllLimit: 39 findAllOrderBy: 39 findAllOrderBy:limit: 40 findQuery: 40 findQuery:limit: 41 findWhere: 41 findWhere:limit: 42 findWhere:orderBy: 42 findWhere:orderBy:limit: 42 openCursorAll 43 openCursorAllOrderBy: 43 openCursorQuery: 44 openCursorWhere: 45 openCursorWhere:limit: 45 openScrollableCursorAll 43 openScrollableCursorAllOr derBy: 43 openScrollableCursorQuer y: 44 openScrollableCursorWher e: 45 openScrollableCursorWher e:limit: 46 Persistent Object FrameWork User's Guide, P40-3222-02 Index PersistentObject instance delete 54 find 50 findLimit: 50 findOrderBy: 50 findOrderBy:limit: 51 isPersistent 56 isPersistentObject 56 openCursor 51 openCursorOrderBy: 51 openScrollableCursor 51 openScrollableCursorOrde rBy: 52 postDelete 55 postInsert 55 postObjectCreate 55 postUpdate 56 preDelete 56 preInsert 56 preObjectCreate 56 preUpdate 56 refresh 54 save 54 saveAggregationAttributes 55 saveAll 54 saveAssociationAttributes 55 saveComposite 54 savePrimitiveAttributes 55 266 methods (cont.) PersistentObjectPool instance disable 63 enable 63 flush 63 flushForClass: 64 flushForObject: 64 initializeInstanceVariables 64 isActive 64 isActive: 64 ScrollableObjectCursor instance first 60 isScrollableObjectCursor 60 last 60 previous 60 setPositionTo: 61 size 61 transaction manager instance begin 62 commit 62 rollback 62 MFAtlas class 129 MFBroker class 34 MFConcurrencyManager class 129 MFDatabase class 34 MFSQLBroker class 34 MFSQLGenSpecBroker class 34 Modeling Base application 82 Modeling Tool 20 models, definition 17 O object cursors definition 32 services 58 using to test maps 173 object databases description 24 theory, suggested reading 24 object integrity 79 object pools activating 64 disabling 63 enabling 63 flushing 63, 64 services 63 verifying state 64 object storage 24 ObjectCursor instance methods close 58 current 58 isObjectCursor 58 isOpen 58 next 59 open 59 position 59 object-oriented development 12 systems design 17 object-retrieval services 38 N names, atlas 132 next, ObjectCursor instance method 59 nondestructive transformation 78 normalization 25 Persistent Object FrameWork User's Guide, P40-3222-02 Index 267 objects adding, example 235 creating an instance (CarSale tutorial) 227 definition 12 deleting 169, 237 dependent 156 encapsulation 13 making persistent 23 manipulating 54, 55, 56 modeling 17, 179 persistent 23 proxy 32, 73 relationships among 14 retrieving 38–48, 58–61 saving 169 setting attributes, example 243 sorting, example 238 transient 23 versus classes 13 ObjectStudio Designer 19 Desktop 100 development environment 19 loading applications 100 Modeling Tool 20 saving images 101 observations, Benchmark class method 89 one-to-many relationships 14 one-to-one relationships 14 open, ObjectCursor instance method 59 openCursor, PersistentObject instance method 51 openCursorAll, PersistentObject class method 43 openCursorAllOrderBy:, PersistentObject class method 43 openCursorOrderBy:, PersistentObject instance method 51 openCursorQuery:, PersistentObject class method 44 Persistent Object FrameWork User's Guide, P40-3222-02 Index openCursorWhere:, PersistentObject class method 45 openCursorWhere:limit:, PersistentObject class method 45 openScrollableCursor, PersistentObject instance method 51 openScrollableCursorAll, PersistentObject class method 43 openScrollableCursorAllOrderB y:, PersistentObject class method 43 openScrollableCursorOrderBy:, PersistentObject instance method 52 openScrollableCursorQuery:, PersistentObject class method 44 openScrollableCursorWhere:, PersistentObject class method 45 openScrollableCursorWhere:li mit:, PersistentObject class method 46 optimistic locking 33 P Paradise demo adding an instance 235 deleting an instance 237 description 183 loading 231 main form 233 overview 229 selecting instances 238 setting instance attributes 243 parent classes 16 partitioned class maps 150 persistency 23 persistency services 53 PersistencyBroker class 35 PersistencyBrokerManager class 35 268 PersistencyRequestBroker class 35 persistent classes 169 persistent frameworks, definition 28 Persistent Object Framework, components 28 persistent objects 23 persistent stores databases 24 files 24 PersistentObject class 35 PersistentObject class methods findAllLimit: 39 findAllOrderBy: 39 findAllOrderBy:limit: 40 findQuery: 40 findQuery:limit: 41 findWhere :limit: 42 findWhere: 41 findWhere:orderBy: 42 findWhere:orderBy:limit: 42 openCursorAll 43 openCursorAllOrderBy: 43 openCursorQuery: 44 openCursorWhere: 45 openCursorWhere:limit: 45 openScrollableCursorAll 43 openScrollableCursorAllOrde rBy: 43 openScrollableCursorQuery: 44 openScrollableCursorWhere: 45 openScrollableCursorWhere:l imit: 46 Persistent Object FrameWork User's Guide, P40-3222-02 Index PersistentObject instance methods delete 54 find 50 findLimit: 50 findOrderBy: 50 findOrderBy:limit: 51 isPersistent 56 isPersistentObject 56 openCursor 51 openCursorOrderBy: 51 openScrollableCursor 51 openScrollableCursorOrderBy : 52 postDelete 55 postInsert 55 postObjectCreate 55 postUpdate 56 preDelete 56 preInsert 56 preObjectCreate 56 preUpdate 56 refresh 54 save 54 saveAggregationAttributes 55 saveAll 54 saveAssociationAttributes 55 saveComposite 54 savePrimitiveAttributes 55 PersistentObjectPool class 35 PersistentObjectPool instance methods disable 63 enable 63 flush 63 flushForClass: 64 flushForObject: 64 initializeInstanceVariables 64 isActive 64 isActive: 64 269 PersistentStore class 36 pessimistic locking 33 POF exception classes 189 position, ObjectCursor instance method 59 postDelete, PersistentObject instance method 55 postInsert, PersistentObject instance method 55 postObjectCreate, PersistentObject instance method 55 postUpdate, PersistentObject instance method 56 preDelete, PersistentObject instance method 56 preferences mapping 115, 120 setting for atlas 115 setting for class 120 preInsert, PersistentObject instance method 56 preObjectCreate, PersistentObject instance method 56 preUpdate, PersistentObject instance method 56 previous, ScrollableObjectCursor instance method 60 primary key definition 25 Mapping Tool icon 109 specifying 124 using in joins 138 primitive attributes, mapping reports 166 proxies. See proxy object proxy object debugging 116 description 32, 73 implementing 76 Q qualifiers, and databases 113 Persistent Object FrameWork User's Guide, P40-3222-02 Index R read-only access 33 reference attributes mapping 144 mapping reports 166 refresh, PersistentObject instance method 54 related installation documentation 93 relational databases joining tables 25 keys 25 tables 25 theory, suggested reading 23, 26 Relational framework, classes 92 Relational Persistent Object FrameWork. See Relational POF Relational POF access layer 21 description 30 relationship maps 144 relationships aggregation 15 among objects 14 association 14 creating 97, 98 gen-spec 16, 118 inheritance 16 loading 102 mapping 144 whole-part 15 reports generating 168 types 166 request brokers 32, 65 requests, transaction 70 reset, Benchmark class method 89 rollback, transaction manager instance method 62 rows, definition 25 270 S Sales Order application description 195 loading 105 UML figure 196 sample applications CarSale tutorial creating database schema 219 creating instance 227 description 217 retrieving information 228 saving an instance 227 setting object attribute 227 Paradise demo adding an instance 235 deleting an instance 237 description 229 loading 231 main form 233, 234 selecting specific instances 238 setting instance attributes 243 save, PersistentObject instance method 54 saveAggregationAttibutes, PersistentObject instance method 55 saveAll, PersistentObject instance method 54 saveAssociationAttributes, PersistentObject instance method 55 saveComposite, PersistentObject instance method 54 savePrimitiveAttributes, PersistentObject instance method 55 saving atlases 159 methods in model file 163, 165 objects 169 Persistent Object FrameWork User's Guide, P40-3222-02 Index schema creating, example 219, 220 generating 180 Schema Generator creating an example schema 219 using 180 script, viewing 181 scrollable object cursors description 32 services 36, 60 ScrollableObjectCursor class 36 ScrollableObjectCursor instance methods first 60 isScrollableObjectCursor 60 last 60 previous 60 setPositionTo: 61 size 61 search example 240 services cursor object 58 scrollable object 36, 60 object manipulation 53 object pool 63 object-retrieval 38 template retrieval 49 transaction manager 62 setPositionTo:, ScrollableObjectCursor instance method 61 size, ScrollableObjectCursor instance method 61 sort example 240 specifying primary keys 124 SQL 21 subclasses in gen-spec relationships 16, 147, 150 suggested reading database theory 23, 24, 26 superclasses abstract, definition 16 setting the default 182, 222 271 synchronization, Smalltalk and database 182 system requirements, Mapping Tool 93 systems building 17 design 17 T tables adding to atlas 123 creating 98 definition 25 joining 25, 138, 145 mapping reports 166 Mapping Tool icon 109 Mapping Tool list box 109 partitioned class map 150 preparing 99 removing from atlases 131 template retrieval services 49 testing maps in atlas 172 maps using an object cursor 173 three-layer architecture 18 time, Benchmark class method 89 timestamps 99, 127 toolbars, Mapping Tool 112 transaction manager description 33, 70 instance methods begin 62 commit 62 rollback 62 services 62 transactionLevel instance variable 62 TransactionManager class 36 transactions commit point 72 committing 62 definition 33 requests 70 rolling back 62 starting 62 transient objects 23 Persistent Object FrameWork User's Guide, P40-3222-02 Index tutorial, CarSale creating database schema 219 creating instance 227 description 183 overview 217 retrieving information 228 saving an instance 227 setting object attribute 227 types of locking 33 types of maps 141 U UFBroker class 36 UFDatabase class 36 UFSmalltalkToDatabaseMaps 185 uninstalling Mapping Tool 95 UniSQL databases 24 UniSQL Persistent Object Framework 31 UniSQL Persistent Object FrameWork. See UniSQL POF UniSQL POF access layer 21 creating a map class demo example 223, 224, 225 procedure 187 development process 179, 180, 181, 182 mapping example 223 overview 185 support 178 purpose 178 UniSQL script, viewing 181 V view layer 19 W whole-part relationships 15 Windows, Mapping Tool system requirements 93 272