Summary
These modes describe how to map business objects into non-dominated databases. Object-oriented and non-directional objects have impensance mismatch because objects consist of data and behavior, and a relational database consists of a relationship between the table and them. Although it is impossible to completely eliminate this impedance does not match, you can divide it to minimize it. The appropriate mode can hide the developer's persistent detail, and let them focus on understanding the domain issues rather than how to persist objects.
Introduction
Object-oriented system developers using relational databases typically take a lot of time to persist, because there is a basic impedance in two technologies without matching. Objects consist of data and behavior, usually inherited, and the relational database includes tables, relationships, and basic predicate calculation functions, which are used to return to the desired value.
In order to avoid impedance between objects and relationships, a method is to use an object-oriented data. However, the system typically needs to store objects into a relational database, some because a system requires a relational theory or the maturity of the relational database, and some because the company's policy is using a relational database rather than the object database. Whether it is why, a system that stores an object to the relational database needs to provide a design of this impedance mismatch.
This article only describes some mode languages that map objects to the relationship, but it describes that we believe that there is no description in other places. All mode Overview can be found in [Keller 98-2], which expounds that the presence is about the design and optimization of relational database [Brown 96] [Keller 97-1, 97-2, 98-1]. Serializer Mode [Riehle et al. 1998] describes how to serialize the object, allowing them to store and acquire, such as text files, relational databases, and RPC buffers to different rear ends, such as text files, relational databases, and RPC buffers.
We used or studied several persistent object systems (Gemstone [Gemstone 96], Toplink [Toplink 97-1, 07-2] and Objectlens [OS 95]). In addition, we use Visaulage for Smalltalk to implement a simple persistence framework for Illinois Department of Public Health (IDPH), which exists in all of these systems. The usage of commercial systems in these modes is usually more thorough than our framework, and we have wanted to buy a persistent framework, but our budget cannot afford them. We need to use a persistent framework for application, involving dozens of data sheets, each application management a patient's medical record information, all applications sharing patient statistics, such as the patient's name, address and hospital, doctor information, and Each app is respectively responsible for a certain field, such as patient immunity, blood test, etc. Although an application can manage a lot of information, at a moment, it will only check one patient. The examples of this article will show you how to use these modes in applications developed for IDPH, and solve the problem of persistent Name and Address objects.
These models are string together, hand drawn handles to solve the impedance mismatch problems mentioned above. A persistent layer exits the developer and the detail of persistence and protecting the developer is not difficult to change. The persistence layer is a special example of building a layer and protects you away from applications and database changes. One of the ways to achieve a persistence layer is through a persistentObject, another method is through a middleman [BMRSS 96].
Read and write to the database require basic creation, read, update, and delete operations, although each object can have their own access database interface, but if your system provides a group of common operations to the persistence layer, then all Objects can be used, such systems are more easily used and maintained. No matter which implementation of the persistence layer, you need to support CRUD (create, read, update, and delete) operations. The CRUD operation will eventually use the SQL code to access the database, and some SQL code descriptions are important to build the actual database SQL call.
When the value is taken from the database or the value is stored back to the database, the system must perform attribute mapping to map the value of the database field value and the value stored in the object properties. Part of impedance mismatch is the relationship and object system has different types of data, mapping objects, and values of the database need to convert the types of two techniques.
Once the object attribute changes, it is important to store them into the database, so any persistent object system should use some change manager to track which objects have changed, so that the system can track what objects have been changed, To ensure saving as needed. Change Manager also helps reduce database access because it only creates transactions for changes that have changed and saved.
Because each object in an object-oriented system is unique, it is important to create a unique identifier for each new object through an OID manager. At the same time, it is also very important to support business, it ensures that an object is an atomic operation, and can roll back this operation via a transaction manager. Any system accessing an RDBMS will provide the connection to the target database through a join manager. The database table name is processed through a table manager, and the field name is also very beneficial.
The mode directory in Table 1 summarizes the patterns discussed herein, which lists the names of each mode, and a brief description thereof.
Pattern name
description
Lasting layer
Provide a layer, map your object to a relational database or other database
CRUD
All persistent objects require at least create, read, update, and delete operations.
SQL code description
Define the actual SQL code, get the value from the relational database, and other databases, and vice versa. It is used to generate SQL code that executes a crud operation.
Attribute mapping method
Map database values and object attribute values, this mode also handles mapping of complex objects, generates objects based on a data row of database tables.
Type conversion
Working with attribute mapping methods, transform between database types and object types to ensure data integrity.
Change Manager
To maintain data integrity, track the change of object values, determine if it is needed to write into the database.
OID Manager
A unique object ID is generated when inserted.
Transaction manager
The transaction mechanism is provided when the object is saved.
Join manager
Get it and maintain the database connection.
Table manager
Manage an object and database table, field mapping
Table 1 - Mode directory
Lasting layer
Alias:
Relationship database access layer
motivation:
If you build a large-oriented business system, save the object to the relational database, you may have to spend a lot of time to deal with how to persist objects. If you are not careful enough, each programmer of the development system has to understand the SQL code and the code accessed, thus being constrained by the database. There will be a lot of work from Microsoft Access to DB2, and even add a lot of variables for an object. So you need to separate your domain knowledge from how you store the knowledge, protecting developers don't sleep for these changes.
problem:
How do I save the object to a non-directional storage mechanism? For example, the relational database, and developers don't have to know the actual implementation.
Specific constraints:
• It is easy to write SQL statements for developers who are familiar with the database;
• Design a good persistence mechanism take time, but it does not provide users with what functionality directly; • Database access costs, usually need to be optimized;
Developers should not worry about how to access the business domain issues in the database in the database;
? There is a common interface using the template method to make the code more easily;
• Use a single interface will force all classes to have a minimum commonality;
• In the life cycle of the application system, the lasting storage type may change;
? In the life cycle of the application system, the business model may often change;
solution:
A persistence layer is provided, which can generate objects from a data store and save data to the data storage source. This layer hides the details of the object storage to the developer, which is actually a special case of building a layer (Layer) [BMRS96], so that you will free from change. All persistent objects use a standard interface for a persistent layer. If the data storage mechanism changes, only the persistence layer needs to be changed. For example, the company's supervisor starts using Oracle in the project, and go to DB2 in the middle of the project.
The system needs to know how to store and load each object, sometimes an object stores in multiple databases on multiple media. An object is part of another more complex object that needs to be tracked which object of it is, which is called owner object. The concept of this owner object is easy to write complex queries, so the persistence layer provides a unique identifier for each object and its parent object, this unique identifier and the parent identifier are very time when implementing the Proxy mode. Useful, can be used as a placeholder of the component object.
Summarize the use of the model name, the persistence layer provides the necessary method, providing the CRUD operation by constructing the SQL code, providing an attribute mapping method, transforming the object data value, accessing the table manager, providing access to the transaction manager, through join The manager is coupled to the database. At the same time, the persistence layer also helps to provide appropriate change management, and cooperate with the OID Manager to provide unique object identity.
There are many ways to achieve a persistent layer, here is listed in one or two.
1. Use an object layer [Keller 98]. Each domain object is inherited from an abstract persisentObject class, know how to perform the necessary Cruded operations. This example is used in this way, and its main benefits are easy to implement. Although it is written in each domain class, these code is separate, easy to find and modify, it can be optimized if necessary, although an exactly-like system is difficult to understand.
2. Using a middleman, it can read the domain object from the database or write the object to the database, and the middleman must know the format of each domain object, generate the SQL statement to read and write. This approach is the most scalable solution to the database code and domain object classes, but there are many basic components.
3. Make a domain object with a set of data objects, which have a one-to-one relationship with a database table. Thus, once a domain object changes, change the corresponding data object, and they will also be saved when the domain object is saved. For example, a value of a pattern can be mapped to the Name and Address data sheets, and the Patient object will have data objects mapped to Name and Address. In VisualWorks, ObjectShare's ObjectLens is to construct a database object in this way. The persistence layer is managed through these data objects, it is easy to implement and easy to understand, although some slow, and developers must maintain one mapping relationship of the database table. Note: The main decision-making basis should be regarded on flexibility, scalability and maintainability requirements.
Implementation example:
Many of the details on the correct description of the construction of the intermediary [BMRSS96] have been completed, and we have more experience in realizing the object, so our example will mainly focus on this mode. Other modes described in the implementation of the middleman will also mention it in our discussion. All of our sample code will describe the implementation based on PersistentObject.
Figure 1 is a UML class diagram showing a persistent layer to map domain objects to the relational database. Note that in this example, the domain object that needs to be persisted is the subclass of the persistentObject, and the persistentObject provides the interface for the persistence layer. The PersistentObject and Table Manager interacts, providing physical table names for SQL code, when SQL code is generated, PersistentObject and join manager interacts to provide the necessary database. If necessary, requests the OID Manager when a new unique identity is needed. In this way, PersistentObject is an intermediate hub, providing any information that needs to be dominated and it is not available. PersistentObject provides a standard interface for the persistence layer, together with other modes, once the SQL code is ready, the SQL statement will be triggered by the database part, in IBM VisuaLage for SmallTalk, these is the abtdbm * application system.
The properties of the PersistentObject are as follows:
• ObjectIdentifier - The unique identifier of the object can be a database key value.
• IsChanged - Sign objects have been modified, telling the persistent layer to write to the database.
• IsPersisted - Sign objects have written to the database.
• OWNINGOBJECT - identifies the parent object, used in the database as a foreign key. Note that this foreign key is in this object rather than the parent object.
The public approach of PersistentObject is as follows:
? Save - Write the object data into the database, it will update or insert a line;
? Delete - Delete the data of an object from the database;
• LOAD - Returns a single instance of a class and its data from the database;
? Loadall - Returns a class of instances from the database, contains all data, which is very useful for returning data for the selection list;
? LoadAllLike - Returns a collection of instances from the database, including partial data;
Figure 1 - Persistent class diagram
Database records can be read in three ways:
? Read a line (persistentObject >> load :); read all records (PersistentObject >> loadall);
• Read all qualified records (PersistentObject >> loadingAllLike)
Specify a particular condition, create a new instance of an object and load the corresponding property set for it, this feature can be implemented by PersistentObject >> loading: and personTentObject >> loadAllLike: method. And when you want a selection list or drop-down list, the PersistentObject >> loadAll method is very useful.
The following sample code describes the PersistentObject described above, which is a common interface method that supports transaction management (detailed later). The read: and SaveAstransaction methods will be detailed in CRUD mode.
Protocol for public interface PersistentObject (Instance)
Load
"Get a single instance of matches its own PersistentObject
| OC |
Oc: = Self loadLike.
^ OC ISEMPTY iFTRUE: [NIL] IFFALSE: [OC first]
LoadAlllike
"Get instance collection that matches its own PersistentObject subclass, the SelectionClause method is the read method of PersistentObject Read method" "
^ Self Calss Read: (Self Selectionclause)
Save
"Save him to the database, which is included in a transaction."
Self Class BegintraSAcction.
Self saveastractions.
Self class endtransaction.
Delete
"Delete himself from the database, which is included in a transaction."
Self class begintration.
Self deleteaStransaction.
Self class endtransaction.
Protocol for public interface PersistentObject (Class)
Loadall
"All instances of returning from the database"
^ Self Read: NIL.
Below is an example code of the Name class, name has Address, so it will have a component that needs to be stored, which is reloaded by any domain object that needs to be stored and has a persistent component.
Protocol for private interface name (instance)
SaveComponentifdirty
"Verify the existence of the Address object and verify that the Proxy mode does not occupy this position, and the Address owner object is set to the current object, and the Save of the Address object is also part of the current transaction."
(Self Address Isnil: [Self address iskindof:
PPLABSTRACTPROXY])
iFtrue: [^ nil].
Self Address OwningObject: Self ObjectIdentitier.
Self Address Saveastractions
in conclusion:
Another benefit that the application developer from the object storage detail is easy to implement domain objects, so the work of the domain model changes. In short, by the function of the package object's persistent mechanism, the developer can hide the details of the target storage. • You can change the database technology without affecting your application code.
• It is easy to change the object to the database to the database, because we have isolated places that need to be changed.
• The user only needs to call the same interface to persistence objects, and the developer does not need to detect if a record is existing in the database.
• It is very simple to implement with SQL code, which may make it more complicated with a persistence layer and sometimes difficult to operate.
• Optimization of persistence layers is difficult. Programmers should implement the evaluation of different ways to decide which one is more suitable for him.
Related or interactive mode:
• The relational database access layer is a very similar pattern that describes a layer that requires persistence of persistent objects.
The hierarchical architecture [Shaw 96] describes the necessary mode to lay back the architecture to isolate changes in development.
• The hierarchical architecture of the information system discusses the implementation details of the development of hierarchical systems.
• The details of the hierarchical system architecture and design are described.
Known application:
? Gemstone Oodbms uses a persistent layer to hide a value of a lasting object. Using the agent for a persistence layer when actually needed, in this example, the storage system is not a relational database.
? Caterpillar / NCSA Financial Model Framework [Yoder 97] Use a persistent layer, all values are stored through a query object. In this example, the application does not store anything object in the database, just getting transactions. However, the persistence layer still hides the details of the database and relational database technology.
? Objectshare VisualWorks SmallTalk ObjectLens [OS 95] uses a persistent layer to map data objects and database tables.
Visualage for SmallTalk also uses a persistent layer and its Abtdbm * applications. VisuaLage provides a graphical coupled GUI builder to form a persistent mechanism.
• Illinois Department of Public Health's Tots and Newborn Screening projects use one and this section examples of implementation methods.
Toplink, Microdoc, SparkY and Object Extencer [Microdoc 98, Sparky 98, OE 98] provide a persistence layer to map objects into the relational database.
• The PLOP registration system implements a persistent layer to save the Java object to the Postgress database [Joe Put the Ref Here].
CRUD
Alias:
Create, read, update, and delete
Basic persistent operation
motivation:
Imagine that you have a Patient class, have Name and Address parts, when you read a pattern, you must read Name and Address at the same time. Write a Patient to the database will be able to write a Name and Address objects. Do they have the same interface to read and write? Maybe some objects need different interfaces? Whether we give the exact same interface, if you can, what?
Any persistent object reads and writes a database, for the newly created object, its value is also persisted, and the object can also be deleted from the persistent storage, so if an object needs to last for a long time To provide at least to provide the smallest operation collection, they are created, read, updated, deleted. problem:
What is the smallest operation collection of a lasting object?
Specific constraints:
? Save all objects in the database requires a mechanism to load yourself, save your own;
• The code placed in one place and writes will help the evolution and maintenance of the object;
• If the class only achieves the same and small interface, it can easily make them nest.
solution:
Provide basic crudation for persistent objects (create, read, update, and delete) operations. Other needs are as follows, LoadAllLike: or loadAll. It is important to provide sufficient information to instantiate objects from the database and save new or changed objects.
If all domain objects have a common PersistentObject> Class, this super class can define crudous operations, and all domain objects can inherit from it, if necessary, the subclass can overload them to improve performance.
If the persistence layer is implemented using the intermediary, the CRUD operation is also implemented by middlemen, whether or not, the persistence must generate SQL code to read and write an domain object. In this way, each domain object must be able to obtain a description of the necessary SQL code to access the cruded database. CRUD and SQL code descriptions are closely collaborate to ensure that these operations can effectively persist domain objects.
Example Implementation:
The previously described PersistentObject provides a standard interface, a basic operation to map objects to database, save, load, and more. These methods are inherited from PersistentObject to access CRUD operations. Some crUD methods need to be rewritten in the domain object. ABTDBM * Database part provides an ExecuteSQL: method to allow the database to perform SQL statements and return a value. Updaterows QL and INSERTROWSQL will be detailed in the SQL code description mode below.
Protocol for Crud PersistentObject (Class)
This method specifies a WHERE clause as an intermediary and returns a set of objects that match the WHERE condition.
Read: assistString
"Returns an object instance collection from the database."
| acollection |
Acollection: = OrderedCollection New.
(Self ResultSet: ASearchString)
DO: [: AROW | Acollection Add: (Self New Initialize: aro)].
^ acollection
Protocol for Persistence Layer PersistentObject (Instance)
These methods save or delete objects for databases, which determines what SQL statements (INSERT, UPDATE, or DELETE) are executed based on object-based values. Once they are determined, the SQL statement will be executed in the data.
SaveAstransaction
"Save yourself to the database."
Self ispersisted iftrue: [Self Update] isfalse: [Self Create].
Self Makeclean
Update
"Update the aggregation class, then update himself in the database"
Self SaveComponentifdirty.
Self Basicupdate
Create
"Insert the aggregation class, then insert yourself in the database" Self SaveComponentifdiRTY.
Self Basiccreate
Basiccreate
"Trigger inserted into the SQL statement in the database"
Self Class ExecuteSQL: Self InsertRowSQL.
IsPersisted: = TRUE
Basicupdate
"Trigger Update SQL Statements in Database"
(Self iskindof: AbstractProxy) iFtrue: [^ nil].
ISCHANGED IFTRUE: [Self Class ExecuteSQL: Self Updaterowsql]
DeleteaStransaction
"Remove yourself from the database"
Self ispersisted iftrue: [Self BasicDelete].
^ nil
Basicdelete
"Trigger delete SQL statement in the database"
Self class
ExecuteSQL: ('Delete from', Self Class Table, 'Where id_obj =',
(Self ObjectIdentifier PrintString)).
in conclusion:
Once your object model and data model analysis have been analyzed, the analysis results can be implemented with CRUD, providing a performance optimized solution, so that developers are separated from performance optimization. Note: If your object model and data model are analyzed, you can provide an optimized performance scheme to your database to implement the CRUD operation to hide the application developer.
How many rows of data (dynamic, static or interboundation) to acquire data flexibility is necessary;
• Simple implementation data is saved to the database, the application developers do not need to decide whether to insert or update objects;
• If the object model and the data model do not have a good analysis, Crud will cause the problem of sub-optimization performance. This will make the developer's work is difficult and have to try other methods.
Related or interactive mode:
? Transaction Manager provides transaction support for these operations;
CRUD and SQL code collaboration, generate the necessary database calls.
Known application:
• Illinois Department of Public Health Tots and Newborn Screening Projects
? Objectshare's VisualWorks SmallTalk ObjectLens [OS 95] uses a CRUD to define how to manipulate the simple data object. Visualage SmallTalk [VA 98] also uses cruds in their Abtdbm * application.
SQL code description
Alias:
Query, update, insert, and delete code definition
Object Query Language (OQL) Description
Universal Query Language (CQL) Description
Structure Query Language (SQL) Description
motivation:
Some places have to be written from the SQL code from the database, update, insert, and delete values to maintain the consistency of object values and persistent stored values. Take a look at the Patient class with Name and Address parts, the SQL code needs to read and write the value of patient, and must also store Name and Address SQL. On the one hand, you can hardly encode SQL to read and write the database, and you can store the value in a common place, develop a structural mapping of the map to the database, and dynamically generate SQL during the running period.
problem:
What is the actual description of the necessary SQL statements required to generate a CRUD operation? Specific constraints:
• When accessing a relational database, the SQL code accessed by the database must appear in some place;
• When the domain model increases, the number of SQL code has increased;
? Writing a valid SQL code requires you to have a deep understanding of the data model and database;
The domain model is likely to change frequently in a life cycle of an application;
• SQL code can be placed anywhere in database access;
• Repeated similar SQL code may cause maintenance issues;
• Generate SQL code from metadata to hide the details of an object to access the developer frame, but there is a balance between performance and maintenance.
solution:
Provide a developer to describe the SQL code to maintain the consistency between objects and persistent storage. At least the domain object needs to know how to perform a CRUD operation (create, read, update, and delete). The necessary SQL code that handles Crud operation needs to be defined in some place.
It is very important to maintain the identity of the object value and the lasting storage value, and provide a means that makes it impossible to make a UPDATE statement as much as possible after modifying a domain object as much as possible.
This mode can be implemented in a variety of ways, but the point is that the SQL statement is packaged and it is easy to associate with persistent objects. SQL code and domain objects are closely associated, then developers have modified a domain object and forget the possibility of updating SQL statements.
One way to implement the two is the real SQL code to be written for each operation, and then let the persistence layers read SQL code from the domain object, create database coupons and execute database calls, middlemen and objects can be dominated from domain Object generates SQL code. Another way is to provide an object query language (OQL), which is a description of the necessary operations required for Crudation, and OQL will be translated into the necessary calls necessary for the database. In addition, you can also describe the CRUD operation using metadata [Foote & Yoder 1998], a CRUD operation translation metadata to build appropriate SQL, most commercial frameworks use this way, they pass some Schema Map [Foote & Yoder 1998] Build this structure, most of these commercial frameworks provide a visualization language to build and manipulate these queries. The implementation and maintenance of the use of metadata and Schema Maps will become more complex, and some non-optimized queries are generated, but they can make developers easy to describe mappings between domain objects and databases, especially when there is visual language assistance This work is time.
If you are implementing a larger-scale system, you have thousands of SQL code and dynamic SQL, they are not fast enough, you may want to replace them or modify them, such as calling the stored procedure, precompiled SQL, implementing push-pull technology Or Cache Technology, this is called optimized query mode [Keller 97-2].
Example Implementation:
When you use a database, you must write some SQL statements to get, insert, update, and delete records, such as the simplest form, as follows:
SELECT * from Table_Name.
INSERT INTO TABLE_NAME (Column_Name) Values (Values)
Update table_name set color_name = xyz where key_value
Delete from table_name
This looks very simple, but how do you get the value from an object to these statements?
You can use a character stream to place the properties of the fixed part and objects in the statement, or you can define the columns you want to get. ASTREAM NextPUTALL: 'SELECT'
NextPutall: column_names;
NextPutall: 'from';
NextPutall: table_name.
or
ASTREAM NextPUTALL: 'INSERT INTO';
NextPutall: table_name;
NextPutall: (Column_names);
NextPutall: 'Values';
NextPutall: (VALUES).
Below is an example of an Name class instance method, and the Name class is a domain object in our example, name and address are mostly available in the management app. This is a simple example of a very small complex object to demonstrate the persistence layer. As mentioned above, the SQL statement is not hard coding. If your database is very similar to your object model, then you can generate from a database Schema These statements.
Protocol for Sqlcode (Instance)
These methods provide actual SQL statements for persistent layers, they will be sent to the database, this SQL statement constitutes a character stream and incorporates the persistence layer. This example demonstrates the use of type converters and table managers, they will be detailed later in this article.
These methods build the SQL statement that is actually sent to the database, for performance consideration, use written characters instead of character splicing.
InsertRowSQL
"Returns an insertion SQL statement, which contains the value from the object."
| ASTREAM |
ASTREAM: = WRITESTREAM ON: (String New).
ASTREAM NextPUTALL: 'INSERT INTO';
NextPutall: Self class table;
NextPutall: '(id_obj,
ID_OBJ_UWN,
NAM_FST,
NAM_LST,
NAM_MID,
EML_ADR,
ORG_NAM,
NUM_PHO)
VALUES;
NextPutall: (Self TypeConverter Prepforsql:
(Objectidentifier: = (Self getKeyValue))))));
NextPut: $ ,;
NextPutall: (Self TypeConverter Prepforsql:
Self OwningObject);
NextPut: $ ,;
NextPutall: (Self TypeConverter Prepforsql:
Self first asuppercase);
NextPut: $ ,;
NextPutall: (Self TypeConverter Prepforsql:
Self last asuppercase);
NextPut: $ ,;
NextPutall: (Self TypeConverter Prepforsql:
Self middle asuppercase);
NextPut: $ ,;
NextPutall: (Self TypeConverter Prepforsql: (Self email);
NextPut: $ ,;
NextPutall: (Self TypeConverter Prepforsql:
Self Organization);
NextPut: $ ,;
NextPutall: (Self TypeConverter PrepForsql: (Self Phone));
NextPutall: ')'.
^ ASTREAM Contents.
Updaterowsql
"Returns an update SQL statement, including the value from the object" | ASTREAM |
ASTREAM: = WRITESTREAM ON: (String New).
ASTREAM NextPUTALL: 'UPDATE';
NextPutall: Self class table;
NextPutall: 'set nam_fst =';
NextPutall: (Self TypeConverter Prepforsql:
Self first asuppercase);
NextPutall: ', NAM_LST =';
NextPutall: (Self TypeConverter Prepforsql:
Self last asuppercase);
NextPutall: ', NAM_MID =';
NextPutall: (Self TypeConverter Prepforsql:
Self middle asuppercase);
NextPutall: ', EML_ADR =';
NextPutall: (Self TypeConverter Prepforsql: (Self email);
NextPutall: ', org_nam =';
NextPutall: (Self TypeConverter Prepforsql:
Self Organization);
NextPutall: ', NUM_PHO =';
NextPutall: (Self TypeConverter PrepForsql: (Self Phone));
NextPutall: 'where id_obj =';
NextPutall: (Self TypeConverter Prepforsql:
Self ObjectIdentifier).
^ ASTREAM Contents.
This method provides WHERE clauses for SQL SELECT statements, each class has this method to determine what WHERE clauses can be used in the SELECT statement.
SelectionClause
"Get a string of a WHERE clause"
| ASTREAM APP |
ASTREAM: = WRITESTREAM ON: (String New).
(Self Objectidentifier ISNIL)
IFFALSE: [ASTREAM NextPUTALL: 'ID_OBJ =';
NextPutall: (Self Class TypeConverter prepforsql:
Self ObjectIdentifier).
^ ASTREAM Contents].
(Self OwningObject Isnil)
IFFALSE: [ASTREAM NextPUTALL: 'ID_OBJ_OWN =';
NextPutall: (Self TypeConverter prepforsql: self igningObject)].
^ ASTREAM Contents.
Protocol for Sqlcode (Class)
These methods provide a table name for the above approach and define which columns will return from the database in the WHERE clause generated above.
TABLE
"Return the table name from the table manager."
^ TableManager GetTable: 'Example'
BuildsqlStatement: Astring
"Returns the SQL statement read for the object."
| ASTREAM |
ASTREAM: = WRITESTREAM ON: (String New).
ASTREAM NextPUTALL: 'SELECT
ID_OBJ,
ID_OBJ_UWN,
NAM_FST,
NAM_LST,
NAM_MID,
EML_ADR,
ORG_NAM,
NUM_PHO from ';
NextPutall: Self Table.
((Astring isnil) or: [astring trimblanks itempty])
IFFALSE: [ASTREAM SETTOEND;
NextPutall: 'where';
NextPutall: astring].
^ ASTREAM Contents.
Protocol for SQL Code PersistentObject (Instance)
Each object needs to provide a SQL code description to the persistence layer. If the object does not need some SQL code, it should return "ShouldNotimplement".
InsertRowSQL
^ Self SubclassResponsibility
SelectionClause
^ Self SubclassResponsibility
Updaterowsql
^ Self SubclassResponsibility
in conclusion:
? Flexibility, only returns the need to collect, and the SQL statement can be replaced with other forms, such as storage procedures or precompiled queries, etc .;
• The performance of the SQL statement can easily use the database tool to be judged.
Related or interactive mode:
• SQL code description uses translator mode [GHJV 95] to generate database statements;
• SQL code description Use builder mode [GHJV 95] to provide the same process for different objects;
• SQL code description can generate SQL statements using metadata [Foote & Yoder 98];
• SQL code description needs to know the Schema [Foote & Yoder 98] to generate the correct statement;
• SQL code describes the CRUD operation generating code for a persistent layer;
• SQL code description is generated using a value from the attribute mapping method.
Known application:
• Illinois Department of Public Health Tots and Newborn Screening projects;
• Objectshare's VisualWorks SmallTalk [OS 95] uses SQL code description to define how to perform CRUD operations for simple data objects. Visualage SmallTalk also uses SQL code description in their Abtdbm * applications;
? Gemstone GemConnect [GemConn 98], use SQL code description to read and write object values to a relational database.
Attribute mapping method
Alias:
Map database to object
Mapping object to the database
motivation:
When a row record is obtained from the database, each column must be mapped to an object of the object or a set of properties, similarly, when the value is stored in the database, an object's properties must be mapped to the database in some way. On the field. Imagine the patient's example, a Patient object has a patient's name and gender association, which can be read from the database's patient table, and the Patient object also has an address associated, this value may have an foreign key, refer to another Objects such as Address objects, so that when a Patient object is read, the property maps must be mapped to the Name and SEX properties of the Patient object, while you need to create an Address object, and map it to you. The Address property of the Patient object. problem:
Where is the developer, how to describe the mapping between database values and object properties?
Specific constraints:
• The object is placed in the attribute variable, and the database is placed in the field;
• The mapping of an object to the database table field is not always one-on-one;
• Some objects need to get values from multiple databases, multiple database tables, which are complex objects;
• A non-objective data does not represent hierarchical structure and object types well;
solution:
For each need for persistence, a method of mapping a database value to an object property and a mapping object property to a database value. The persistence layer will use the first method to store the value returned from the database to the corresponding object properties. Similarly, when PersistentObject is stored, the persistence layer will use the second method to send the value of the object to the database. When the PersistentObject generates SQL code, it maps these data.
These methods returns a row from the database and fill in the corresponding object properties, sometimes several fields are mapped to an attribute, which must also get an object's attribute value, write the routine to the database field through a database. Typically, an attribute is mapped to one or more database fields, but sometimes multiple properties are mapped to a database field. Also, attribute values may be generated from different databases of different platforms, and the aggregation class will load from other databases, and the return object is given to the current attribute.
There is usually at least two groups of attribute mappings, one is used to read values from the database, one is to write the value back to the database. When the value has been mapped to the database, the property mapping method needs to provide calls to type conversion.
Metadata can be used to define attribute mappings, can be used with Schema, or you can use it. In this case, the translator will be used to generate an attribute mapping. Visualization languages can also be used to describe mappings, but this method is often difficult to implement and maintain, but once the developer is easy to map an object's properties.
When an attribute is mapped to another domain object, it is usually used to delay initialization, such as the Patient example mentioned above, because there are very little address information, one agent can be used to initialize the Address property, after when Need to access the patient's address, the patient's address information will be read from the database and create the Address object. In this example, the Address property is also updated to point to the newly created Address object.
Instance implementation:
Once the data is removed from the database, they will move from the returned row to the object properties, and the return line (VisuaLage) is a dictionary structure, which can be accessed below:
Arow at: KeyValue.
Next, you have to give the value to the property: attribute: = (AROW AT: KeyValue).
Or, if the property wants to include one other class instance:
Attribute: = ((Class New) OwningObject:
Objectidentifier; Youself) loading.
The instance of an Address class will be loaded from the database and assigned to the property. If the address information containing the database is in different databases of different platforms, the Address class will be loaded from other databases.
Below is an attribute mapping method of the Name class, which shows how to map the database to the object and the application type conversion process. SQL code description mode shows how to map objects back to the database.
Protocol for Map Attributes (Instance)
These methods receive a line from the persistentObject >> Read: method, and each row of the data table is incorporated into a new instance (initialized by the persistentObject), each element in the row is assigned to the properties, Type conversion, for complex objects, the attribute value is sent by sending a persistentObject >> Load: (if it is a collection, send the persistentObject >> loadAllLike :) to the property class type, this method uses a conditional statement SQL code description instance. For example, in the Name class, you will send a loadAllLike: message to the Address class, and use ObjectIdentifier as a parameter, which will load all OwningObject as the same name address.
Initialize: Arow (Name Class)
"Enter an object instance from a data line."
Objectidentifier: = Self TypeConverter Converttonumber:
(Arow at: 'id_obj').
OwningObject: = arow at: 'ID_OBJ_OWN'.
IsPersisted: = true.
First: = Self TypeConverter ConvertTOUPPERSTOUPPERSTOUPPERSTOUPPERSTOUPPERSTOUPPERSTOUPPERS
(AROW AT: 'NAM_FST').
Middle: = Self TypeConverter ConvertTOUPPERSTOUPPERSTING:
(Arow at: 'NAM_MID').
Last: = Self TypeConverter ConvertTOUPPERSTOUPPERSTOUPPERSTING:
(Arow at: 'NAM_LST').
Email: = Self TypeConvertT7tring:
(Arow at: 'EML_ADR').
Organization: = Self TypeConvertToupPerstring:
(Arow at: 'org_nam').
Phone: = Self TypConverter Converttonumber:
(Arow at: 'num_pho').
Address: = ((Address New) OWNINGOBJECT:
Objectidentifier; Yourself) load
in conclusion:
• When the database structure changes, just change a place;
• There is no consistency in the property name and database table character name;
? Newly entered the project developers easy to correspond to the library table field name and attribute name;
• With the evolution of the database and domain objects, the property mapping method needs to be maintained. Related or interactive mode:
• Type conversion is required in mapping values to databases and from database mapping values;
• When requesting a call to a persistent layer to read and write a database, you want to generate the SQL code required for the attribute mapping method;
Metadata can be together with a schema, used to define attribute mappings, or possibly using a translator to generate actual mappings.
Known application:
• Illinois Department of Public Health Tots and Newborn Screening projects;
? ParcPlace VisualWorks SmallTalk [OS 95] uses attribute mapping methods to define how to process mappings between properties and data objects. Visualage SmallTalk [VA 98] also uses attribute mapping methods in their Abtdbm * application.
• The ResultSet class in JDBC is a data line, his method such as getint (), getString (), getDate () is a property mapping, and is also a type conversion of the reader. Mapping back to the database back in the JDBC, the PerpARedStatement class constructs the SQL statement, and in question mark '? 'As the placeholder of the parameters, there is a set of setint (), setString (), setdate (), and so on.
Gemstone GemConnect maps the database field to the object properties.
Type conversion
Alias:
Data conversion
Type translation
motivation:
The database value type is not always corresponding to the object type, for example, a Boolean value may be t or f in the data inventory, in the patient example, the gender can be an attribute, stored in a class named SEX, male instance Some behaviors, and female instances have different behaviors, perhaps their values in the database are M and F, when this value is read from the database, M needs to be converted into a SEX class male instance, f needs to convert to SEX classes Female example. Type conversion allows the conversion between object values and database values.
problem:
How to map a object without a database type to a database type, and vice versa?
Specific constraints:
• The value in the database may not be mapped to the specified object type;
• There is a impedance mismatch between object types and database types;
• The values in the application can be edited and stored in the database by other applications;
• Object properties and database field values can all have strings and numbers, which reduces impedance mismatch;
solution:
Converts all values into their respective types through a type converter object, know how to handle null values and other object values and database values. When an object is persisted from a large multi-applied database, the data format will be a variety of data, which ensures that the data obtained from the database can be adapted to the object.
Make sure that the data read from the database is important to work for objects, and it is also important to follow database rules and maintenance data from objects to database rules and maintenance data.
Each object property passes the appropriate type converter, for a specific application system and DBM application necessary data rules, data rules applied in the domain-level application more efficient than in the interface level, which is usually due to all Domain objects use a set of common type conversions.
Imagine some old databases without null values (NULL), they actually store an empty string for "no data", when reading this value, returns an empty character that represents "blank data" Strings, he relies on the rules definition of the database and the application. This type of conversion can be completed directly in the mapping code, and the data type will be converted into an appropriate object type, or vice versa, usually, a group of common conversions can be abstract. For example, a Boolean object can map T or F in the database, and TimeStamps can be mapped to String, and a NULL can map to an empty string. When you have these common conversions, you can call the appropriate routine to convert the pre-processing type, which form a part of strategy [GHJV95].
Depending on your needs, implementation is a variety of diverse, in the following example, place all conversion methods in an object, which makes the method in one, if necessary, allows dynamically switching the converted object. In this way, different conversion algorithms can be applied to different databases for different databases. If the surplus applications, the converter is no longer needed, will be a cleaner way.
Another option will expand each affected or used base class, each object will know how to convert them into a database must be format, suppose you use multiple databases, then each method needs to adapt to this format Differences.
There is also a way, put all your conversion routines in PersistentObject, if you need to map a new database or change, you have to modify the code. This method exists in any object that is inherited from the persistentObject, similar to the previous option, when you have multiple databases, the situation is similar.
All mentioned methods can be operated independently of the selected persistent mechanism.
Instance implementation:
When you generate properties from a row of dictionary structures from a database:
Attribute: = (Arow At: Key).
This can complete the task, however, if the database value does not guarantee the required object, then the code you use this property will fail, when you apply type conversion, such as:
Attribute: = Self TypeConvertTOUPPERSTOUPPERSTOUPPERSTOUPPERSTOUPPERSTOUPPERSTOUPPERSTING
(AROW AT: KEY).
This attribute value will be required by the application, which will first get the class responsible for conversion, then pass the database value to a method to ensure that the attribute value of a larger string is generated.
The situation in which the property value of the prepared object is stored, and you can simply put the attribute value into a character stream.
NextPutall: (Attribute) PrintString.
This can also complete the task, however, if you don't know the PrintString, then this code will fail. Should The Database ... a Conditional Statement. When you apply type conversion, such as:
NextPutall: (Self TypeConverter Prepforsql:
(attribTute asuppercase)).
The attribute will be converted into an appropriate format, as described above, the class responsible for the conversion is obtained and the attribute will be converted.
Type conversion method Access to PersistentObject can be prepared to deploy the value of the database, or the row returned by the database into object properties. Initialize: and INSERTROWSQL: Method (in each domain object) shows an example of type conversion.
Protocol for Type Conversion PersistentObject (Instance)
This method determines which class is responsible for the type of table type and object type conversion type, which can extends, which database is determined which database or which class is used to convert the type.
TYPECONVERTER
"Returns the class responsible for type conversion"
^ TypeConverter
Protocol for Type Conversion TypeConverter (Class)
These methods provide consistently formatted data values for PersistentObject, when converted from an object (TypeConvert >> PrepForsql :), according to the database needs to be determined and formatted; when converting from the database, the database is perhaps Not the object / application, in the property mapping method, each attribute transitions to ensure that the data value is correct. In some cases, a default value is provided when the database does not contain data. When several different implementation applications use the same database, data rules do not need to force compliance in the database level.
ConvertToBooleanfalse: Astring
"Returns a Boolean value from a string, non-valued is default."
^ 'T' = Astring Asstring Trimblanks Aslowercase
Convert7tring: Astring
"Returns a string from a database string or character, the default is a new string."
^ Astring Asstring Trimblanks
Converttonumber: Anumber
"Returns a number from a database number, default is 0."
^ Anumber isnumber iftrue: [Anumber asinteger] iffalse: [0]
This method converts an object into a correct database format, placed in a character stream, the object is measured why the type returns the appropriate format, forming the SQL code is placed in the character stream. This provides a common format for the persistent layer data type. The default date format in this example is assumed (local current time: '% m% D% Y'). If you don't want to use a full date format, the date of the date should be modified according to your database. Note: These format types are supported by IBM DB2 UDB V5.0.
Prepforsql: anObject
"Returns objects with appropriate format in the form of a character stream."
Anobject Isnil iftrue: [^ 'Null'].
Anobject isstring
IFTRUE:
[anObject ISempty
iFtrue: [^ 'null']
IFFALSE: [^ anObject Trimblanks Printstring]].
Anobject isnumber iftrue: [^ anObject PrintString].
Anobject Abtcanbedate iftrue:
[^ anObject PrintString PrintString].
Anobject AbtcanbeBoolean iftrue:
[Anobject iftrue: [^ 'T' PrintString]
IFFALSE: [^ 'F' PrintString]].
ANOBJECT ABTCANBETIME
iFtrue: [^ Self DatabaseConnection DatabaseMgr
Sqlstringfortime: anObject].
(Anobject iskindof: PPLPERSISTENTOBJECT)
iFtrue: [Anobject ObjectIdentifier ISNIL
iFtrue: [^ 'null']
IFFALSE: [^ anobject objectidentiDentifier printstring]] Conclusion:
• Can help ensure data consistency;
• There are many types of object types and have nothing to do with the database type;
• You can assign a default for null values read by the database;
• Block "Undefined Object Does Not Understand" error from being "not understood";
• Enhanced RMA (reliability, maintainability, and accessibility) for applications;
• The type of conversion requires time, especially when reading a large number of values from the database;
Related or interactive mode:
? Policies [GHJV 95] can be used to implement this mode;
• When constructing SQL code, the attribute mapping method call type conversion;
• The SQL code description may embed type conversion.
Known application:
• Illinois Department of Public Health Tots and Newborn Screening projects;
• Objectshare's VisualWorks SmallTalk [OS 95] uses type conversions to convert between database types and object types. Visualage for SmallTalk also uses type conversions in their Abtdbm * applications.
Gemstone GemConnect transitions between database types and object types;
? Toplink also provides type conversion.
Change management
Alias:
Haschanged
Isdirty
Laundry List
Object manager
motivation:
Usually using a patient management system is to increase his record and add a record for patients who have recently visited patients. However, sometimes the patient's address has changed, and if an actual change occurs, the system should only write back to the patient's address.
One of the ways to implement this is to provide a separate change address, a separate update button to write the address back to the database, but this is awkward and needs to maintain a lot of code; better way to make the patient management system The user edits the address when necessary and allows the system to write only changes to the address object and other users determine the value to be written.
Overall, a persistence layer should track all of the stateistentObject's change status and make sure they have to write back to the database.
problem:
How to determine an object change, and need to save into the database? Prevent unnecessary access to the database, make sure the user knows when some values have changed and is not saved before exiting the program.
Specific constraints:
? Most objects have never modified after reading;
• Saved without changing is a waste time;
? Developers often forget to save a modified object, and the user is worse;
• If every modification of the object is written to the database, then in order to cancel the user's request, another write or rollback operation is required;
• Complex objects may have only one component to modify, there is no need to write all the values to the database;
• Write the object that is not modified to the database, which will be difficult to identify who will finally modify this object;
solution:
Set a change manager to track any persistentObject to modify a lasting property, whenever, request saving objects require this change manager. One of the ways to achieve it is to inherit a class from PersistentObject, which has a dirty bit, once a change in the property value mapped to the database is set. This dirty position is usually a Boolean instance variable that indicates whether an object changes. When this Boolean value is set, the PersistentObject will save the new value into the database when the PersistentObject is saved. Otherwise, PersistentObject will ignore the write database.
Laundry List is also a mode for saving data, which is stored in a laundry basket, and then you can control what you do, and it is also tracking which properties have changed, thus only saving dirty Attributes. Thus, if an application changes a number of fields, and another application changes other fields, you can ensure that you only update the field you change, he can help the application concurrently modify the database table.
There are many types of implementation according to the different system. One solution is to modify the attribute setting (SETTER) method, you can set a flag when the object value is modified, or the object can also be added to the laundry list of the changed object, which is very simple but effective. Another solution can use similar to method packaging [BRANT, FOOTE, JOHNSON, & Roberts 1998], and do the same thing in the property setting method. There is also a solution that initializes lasting attributes into a dependent mechanism. Once a attribute value is modified, you can set the dirty position or you can add the object to the laundry list, and delete dependence; a dirty dirty. Another implementation method is to use metadata to describe all persistent attributes, whenever the state changes the status of the object, can use metadata to determine whether the object varies, and the method package can use this metadata to provide similar services.
Data access is generally very expensive, which should be saved, and it will be remarkable to provide a significant performance by marking whether an object needs to be written to the database. In addition to performance, it also helps the user interface prompts users before exiting. This feature makes users easier to accept your application, which allows them to know that they have forgotten the changed information, and the system will prompt them to save. The user will form a conclusion if they have to repeat the same data, this system is very fast.
Another feature of the Change Manager is to provide a memory function of the initial state or changing state, which can be implemented by MEMENTO [GHJV95]. If your system needs to return to the initial state, the change manager can keep the initial value, pass through Call an undo operation to complete. At the same time, you can also provide multi-step revocation operations for your system.
If you have an object, it is an ordered collection of other objects. Database line message? One way is to set the key value of the instance to nil, then the domain object provides an IsValid method, determines that the delete is a specific row, which can be implemented, but the application system programmer has to process all NIL instances with a specific code. A better way is to use a deletion manager, when the user presses the button (or other mechanism), the application system programmer places the deleted instance, because each object knows how to delete itself, The instance will be deleted from the collection and databases. The Delete Manager is a Singleton [GHJV95] object that retains the deleted instance until the user sends or cancels. Instance implementation:
This example will show an Accessor method how to set dirty positions for the first attribute of the Name class, which generates additional MakeDirty calls in VisuaLage, which will inherit the ISChanged The property is set to a true value.
First: astring
"Save the first value."
Self Makedirty
First: = astring
Self signalevent: #first
With: astring
Protocol for change Manager PersistentObject (Instance)
These methods provide the function of changing the dirty logo for the persistence layer, which avoids the persistence layer to write to the database that has not changed data, and also provides a method of testing a test object to the GUI programmer to provide the user to save the data prompt. information.
Makedirty
"Indicates that an object needs to save into the database, as in the previous example, this method can be called in the setter method."
ISCHANGED: = True.
Makeclean
"Indicates that an object does not need to save a database or object has not been changed."
iSChanged: = false.
in conclusion:
• Users will be more happy to accept this application;
• Do not write data to the database to the database, to ensure that the database has better performance;
• When the data is fused between the database, the flag can be set so this record will insert a new database when necessary;
• Related or interactive mode:
Related or interactive mode:
? State [GHJV 95] is an alternative to the Boolean value flag;
? MEMENTO can be changed by the Change Manager to support undo operations;
• Laundry list can track all changes that have changed;
• You can use the Delete Manager to assist in deleting a part of complex objects;
• Object Manager [Keller 98-2] is a very similar mode.
Known application:
• The operating system uses dirty bits for virtual memory;
Most DBMS use dirty positions in the cache [Keller 98-1];
• Cache generally use dirty bits;
• Illinois Department of Public Health Tots and Newborn Screening projects;
• In GemStone Oodbms, use a change manager to track when an object is changed, so you can know when an object needs to be saved to the server. • Objectshare's VisualWorks SmallTalk [OS 95] uses the Change Manager to indicate whether an object value has been changed. VisuaLage SmallTalk also uses the Change Manager in their Abtdbm * application system. VisuaLage provides graphical coupling for the GUI builders to provide a persistent mechanism.
OID Manager
Alias:
Unique key value generator
motivation:
As long as an object is persisted, the uniqueness of the object is very important. In an object-oriented system, all objects are unique, so given a unique identifier for each object, which is often referred to as OID. OID Manager ensures that all objects generate unique key values and store them into the database.
problem:
How do we make sure that each object is unique in the database, regardless of whether or not other objects share a similar state?
Specific constraints:
• You will not want to change the key value and repetition key value in a database, the database administrator thinks this is very bad;
• Increase ID is sometimes artificial, usually need to increase additional fields in the table;
• Create a unique key value for the distributed database;
• Create a single key value for the SQL code to create a record.
solution:
Provide an OID manager to create a unique key value for all objects that need to be stored in the database, make sure all newly created and persistent objects can get a unique key value. When a new object requires persistence, it will be written to the database and there is a unique identifier generation, which requires very fast and requires uniqueness of the identification.
One solution is to generate random numbers. Once a number is generated, it must be checked if it has been used. However, when running in multiple databases, it is not possible to know, the time required, and when data is fused from multiple database, the key value is more likely.
Another scheme is to store the last use of the last use in the local table, and combined with a local and unique key value, which requires each key value to read and writes the key value table.
A better method (in this example) is a variant of a method, which can reduce the need to write each key value [AMBLER 97]. When a key value is required, request a Singleton instance if there is no number (for example, write) in this instance, a number of numbers is read from a table. Once this number is returned, it will immediately add a specific number (application specified), and write back the database to access the next other user. This number returns to the call object and adds 1, stored in memory until a key value is required next time. When the numbers of this segment are running, they will re-read into a segment and repeat the above process.
You can use a key value to generate a policy to create these keys, a database or site can use an algorithm, while another can use other algorithms, it is important that key values are unique in the table, preferably throughout the database or multiple The database is unique.
Some databases have a method of generating a unique key value, which requires emphasizing if you have multiple servers, generating an algorithm cannot conflict. You can also use a TCP / IP address and / or hard disk serial number to keep up with other numbers to ensure the uniqueness of the object identity. At the same time, some databases have a method of generating a sequence number, which can be used as an OID, regardless of what algorithm you use, ensuring thread security is very important.
Note: This is linked to the UNIQUE KEY mode in the Kellers and the Browns mode language. Example Implementation:
The OID Manager provides a unique identifier for the long-lasting layer providing domain object, which can be used as the key value of the database. OID Manager maintains a table, there is a number in the table, when it cannot return a legitimate key value to the persistence layer, the OID manager adds this number and writes back. In this example, when it does not have a legitimate number, a number of digital maintenance is obtained from the table until the number exceeds the number of writing back. The size of the paragraph in this example is 10 (see the increment method below).
Protocol for Accessors OidManager (Instance)
This method returns a value that is the size of the digital segment obtained from the database when a new number is required. It can be set when the application system is started and does not want to set it to 10. Don't understand
increment
"Returns an increased value."
(increment isnil)
iFtrue: [increment: = 10].
^ increment
Protocol for Key Generation OidManager (Instance)
This is the core method of this mode, reads a field value from the table, and all users use it. When a value is read, it immediately adds the value stored in the Increment property, which defaults to 10, and the new value will then be written back to the table to be obtained by the next use and the next user. This value initially reads and stores in the property, manipulating the manipulation to provide a unique value, this number will attach the key value of the site (or database) to create a unique number of 14 or 15 digits.
Readkey
"Generate a unique key value to put the object to the database"
| Newkey AQuerySpec ARESULTSET AMAXKEY PREP |
PersistenceObject Begintractions.
AQuerySpec: = AbtquerySpec New
Statement: 'Select Num_SEQ from Sequence'.
ARESULTSET: = PersistenceObject DatabaseConnection
ResultTableFromQuerySpec: AQuerySpec.
AMAXKEY: = ARESULTSET FIRST AT: 'NUM_SEQ'.
NEWKEY: = AMAXKEY SELF Increment.
PersistenceObject
ExecuteSQL: 'Update Sequence Set Num_SEQ =', Newkey PrintString.
PersistenceObject endtransaction.
Prep: = Self Class Sitekey * Self Keysize.
Self lowkey: Prep AMAXKEY.
Self Highkey: Prep (NewKey -1).
^ nil
Protocol for Key Retriever OidManager (Instance)
This is a method of obtaining a key value to check this property, see if you need to read a number through the above method, or add a single instance to 1 and return it.
getKey
"This is a way to get a key value."
Self currentkey = 0 iftrue: [Self Readkey].
Self currentkey = Self HighKey
IFTRUE:
[Self Readkey.
^ Self CurrentKey].
Self Currentkey: Self CurrentKey 1. ^ Self CurrentKey
in conclusion:
• Always add numbers that will waste digital values when writing back to database tables;
• When writing a database table, if the number increases, it will consume time;
• The only single-field key value can improve performance and make SQL encoding easier and easier abstraction.
Related or interactive mode:
? One OID Manager is a single real example, all lasting objects generate their key values in a common place;
• You can use a policy to generate a key value.
Known application:
• Illinois Department of Public Health Tots and Newborn Screening projects;
• All ODBMS uses a key value generation algorithm to create a unique key value for saved objects;
• PLOP Registraion uses the Microsoft Access sequence database command to generate a unique key value;
• In DCOM, each interface is identified by their interface ID (IID) in the runtime. The IID is a global unique identifier generated by DCOM. GUID has 128 bits, generated by the DCOM API function CocreateGuid, which uses the algorithm specified by OSF DCE, which uses the current date and time, NIC ID, and a high frequency counter. Basically, you can use tools (such as Microsoft Developer Studio) to get these GUIDs and put them in your DCOM IDL.
Corba 2.0 has a joint interface warehouse - a warehouse operating between multiple ORBs. To avoid naming conflicts, the warehouse is the only ID of the global interface and operation assignment (CORBA called a warehouse ID). A warehouse ID is a string, three hierarchical composition, CORBA2.0 defines two formats:
i) The IDL name has a unique prefix, its component composition is: an IDL string, follows a list of identifiers separated by '/', and a hosting version number. The first identifier separated by ':' is a unique prefix - Java used the same way. E.g:
IDL: JoeYoder / Foo / Bar /: 1.0
Joeyoder is the only prefix
Foo is a module
Bar is an interface
II) DCE Universal Unique Identifier (UUID), which uses the UUID generator provided by DCE - such as DCOM. Its part is separated by ':', the first component is a DCE string, the second is the UUID, the third is a version number (no auxiliary version number). E.g:
DCE: 100AB200-0123-4567-89Ab: 1
Transaction manager
Alias:
Work unit
Transactional object
motivation:
In the process of saving the object, it is very important to keep some modes when certain values cannot be saved normally, and the previous storage object can be rolled back. In the patient example, you not only store the properties of the Patient object, but also store the changed address object, if you try to save any patient's address object failed, you want to roll back to save the patient information all the writing Enter the database operation. A transaction manager provides support for starting transactions, submit transactions and rollback transactions.
problem:
How to write to a set of objects when any write fails, there is no object write. Specific constraints:
• The object is usually linked in some way. If an object is not saved normally, then you don't want to save the relevant object;
? Do you know which news is a transaction, which does not have impedance mismatch;
• Each write operation to the database can be set to a single transaction;
• Complex objects can construct a complex SQL statement that contains transaction processing, which can be seen as a work unit.
solution:
Build a transaction manager similar to other transaction managers, this manager allows you to start transactions, end your transaction, submit transactions, and rollback transactions. Transaction Manager is typically mapped to RDBMS transaction manager if it is provided, all popular databases embedded transaction managers, preferably use them.
For the reason, it is important to buffer data, this situation, the function of the transaction manager has the function of submitting and rolling buffer values. If the database you are mapped does not support the transaction manager, then you need to save the initial state of the object when you start your transaction, so when the request rollback, the initial value can write back the data storage.
Example Implementation:
Without transaction management, you will use the following form:
ANOBJECT SAVE.
This will submit the SQL statement sent to the database. If something happens during the save ANOBJECT, you will leave some anobject in the database, especially when Anobject is a complex object.
When you use transaction management, basically you put all the SQL statements built by Anobject, tell the database, don't save all, you don't do anything, this looks like this:
BeGintransaction
ANOBJECT SAVE
AnotherObject Save
Endtransaction
This ensures that all save commands can be successfully executed before submitting changes to the database. When your object is a complex object, it knows how to save his aggregate object, make sure the full object is written to the database.
The following code is extracted from the PersistentObject, which shows the packaging result of implementing transaction management, telling the database to start and stop a transaction, depending on the database you use, and the development language you use. You may need to extend your business to handle your special implementation, and if you saved the database (possibly just a text file) does not support your transaction, you have to develop a complete transaction manager to support the needs of the user. In this example, all saved and deleted objects are packaged in a begintransaction and an endtransaction. The class method is called by the database connection class, which is where VisuaLage provides submission and rollback transactions for the database.
Protocol for public interface PersistentObject (Instance)
Save
Self class beginTransaction.
Self saveastractions.
Self class endtransaction.
Delete
Self class beginTransaction.
Self deleteaStransaction.
Self class endtransaction.
Protocol for public interface PersistentObject (Class)
BeGintransaction
Self DatabaseConnection BeginUnitOfWorkifeRror: [Self DatabaseConnection RollbackUnitOfwork]
Endtransaction
Self DatabaseConnection CommitUnitOfwork
RollbackTransaction
Self DatabaseConnection RollbackUnitOfwork
in conclusion:
• Complex objects should be not fully saved, don't save anything;
? Half-objects cannot maintain reference consistency;
• All other applications that write to the database have to use the transaction manager, you may have to increase the check, see if there is anything else to modify the database when you save;
• It is very difficult to write a complete transaction manager unless the support of the transaction management is embedded in the database.
Related or interactive mode:
• Transaction Manager and Transaction Object [Keller 98-2] is very similar, transaction objects provide objects to start, submit, and rollback transaction by building object package transactions outside the outside.
Known application:
Most database class applications provide similar features or a definition of work units;
• Illinois Department of Public Health Tots and Newborn Screening projects;
? VisualWorks Provides transaction manager in their ObjectLens;
VisuaLage also provides transaction support in the Abtdbm * class;
Gemstone GemConnect provides transaction management for database objects.
Join manager
Alias:
Current
Database session
motivation:
As long as a persistent object is read or written to the database, you must establish a connection between a database. Typical information required for a database transaction is the database name, user name, and user password. This information can be obtained to the user at each access, which will result in failed user verification, because most users do not know the database name or alias. You can also get the username and password at startup, and use the subsequent code to establish a connection information, which leads to a large amount of extra information in the event of unnecessary. The best way is to construct a joint manager, store these global information, and use when any need to access the database.
problem:
How does the persistent manager track the currently connected database and join users?
Specific constraints:
• All database clusters need to access a place to establish a connection;
? Quote global variables can keep the code simplicity;
• Maintain the current database session, not to create a new session for each transaction will be more efficient and more easily;
• Provide necessary coupled information and operations in a place to make the code easy to understand and maintain.
solution:
Create all the data values required to join the user database, the common value is usually a database session, logging in to the current user of the system and other global information for audit, transaction, and other similar.
When an application requires only one copy, you can use Singleton mode [GHJV 95] or use a single activity instance and a session [Yoder & Barcalow 97], this single activity instance is in Design Pattern Smalltalk Companion [More Here It is described in 98]. Singleton usually stores a single glion, for example as a class variable or the class itself. Unfortunately, this mode is sometimes destroyed in a multi-thread, multi-user or distributed application. Some situations require a real Singleton, and some cases, each thread or each distribution process can be seen as an independent application, each has its own Singleton, but when the application share a common global environment This single global area cannot be shared, which requires a mechanism to allow multiple Singleton, one for each application. Therefore, the coupling manager is a Singleton that manages any and database session. The join manager and persistence are interactive to allow the latter to get the currently required database connection. The join manager also interacts with the table manager to provide any database table name for any established join. In this way, the policy [GHJV 95] mode can be used again to select the appropriate database and table mapping. Imagine that you may save your value to five databases, for speed considering, you will choose a minimum load, and use a batch process to synchronize all libraries in a primary database. This distributed database system ensures an ideal performance through a policy mode method.
Example Implementation:
Based on the information, link manager established and database connection based on the information obtained from the table manager. When the persistence layer requests a join, the join manager provides an interface to the database with database components through ODBC, CLI, or other possible ways. Once the coupling cannot be obtained at the time, or the interrupt is interrupted, the join manager provides an error block for error handling, and provides an error collection to record errors, if possible, recovery.
Simply put, when a domain object says:
Self DatabaseConnection
Just return the join, join type, and which connection, connection type, and which use multiple coupling) are determined by the join manager.
In our example, both local, also have a remote database. We show how you will interact from VisuaLage and Abtdbm * to get the links to the local database.
Protocol for public Interface ConnectionManager (Class)
DatabaseConnection
"Check local variables to see what join, or look back."
^ Self getLocal
iFtrue: [Self LocalConnection]
IFFALSE: [Self RemoteConnection]
LocalConnection
"Returns a join to PPLPERSISTENTOBJECT, check whether the name has opened a join, if not, create one, and provide error handling, handling the incorrection of the join and join open."
| Connection |
(Connection: =
Abtdbmsystem ActiveDatabaseConnectionwithalias: 'Example') ISNIL
IFTRUE:
[Connection: =
((AbtDatabaseConnectionSpec)
FordBmclass: #abtodbcdatabasemanager
DatabaseName: 'Example')
PROMPTENALBLED: FALSE;
Connectusingalias: 'Example'logonspec: (AbtdatabaseElogonspec)
ID: ''
PASSWORD: ''
Server: '')
IFERROR: [: Error | PplerrorCollector dbconnectionerror])
AutoCommit: false;
Yourself].
"If the development environment does not use the error block, you need to provide a debugger, set to call the Error Collector in the Runtime Error Block, which handles all DBM class errors for the manager, the above error block is specific to join."
Connection DatabaseMgr
ErrorBlock: (System StartupClass Isruntime
iFtrue: [[: Error | PplerrorCollector DBMERROR: Error]]
Iffalse: [NIL]).
^ Connection
in conclusion:
• The join manager provides connection information for all persistent objects;
• When the coupling information changes, simply modify it;
• It provides a way to support multi-join, which can be used to load an object from the database, or balance the load of the database.
Related or interactive mode:
• In multi-thread, multi-user or distribution environment, the join manager is an alternative to Singleton;
• The link manager and session are similar, and its maintenance and database sessions and global information associated with database connection.
• The join manager can use a policy to select the current connection;
Known application:
• GEMBUILER for VisualWorks, Lens Oracle Framework and Gemstone, has ORACLESession and GBSSession, which store transaction status and database associated information, which is referenced by any object in the same database environment;
Caterpillar / NCSA Financial Model Framework has a FMState class [Yoder 97], as a session and maintenance of the joint manager;
? VisuaLage has the trajectory of Abtdbmsystem, maintaining the activity, calls the VA class, and controls the physical join in turn.
• Illinois Department of Public Health Tots and Newborn Screening projects.
Table manager
Alias:
Data Dictionary
Table map
motivation:
Over time, the permanent storage of objects may change, or multiple storage. A table manager describes the structure of the table and fields in the database, allowing developers away from these details, so that the naming structure of the database does not affect the application developer.
problem:
How does an object know what table, what field, especially objects need to be stored in multiple tables. When using multiple databases, there will be an order of magnitude.
Specific constraints:
• Map the object to the relational database, which eventually maps the object value to the database table;
• When the application system expands and modifies, the developers hope to quickly modify the table name;
• Map the object to the same table in different places;
• It is easy to switch from one database to another;
• Direct hard coding table name and field names that describe SQL code are very straightforward.
Solution: Provide a place to get the object to get the necessary table, the field name to store itself. When an object is stored, find his table name in the table manager. Very rapid and efficient via only a local definition name string, changes, and test modifications.
This mode uses a SIGLETON [GHJV 95] to return the desired table or field name to the domain object. This single real example includes a dictionary structure storage name that makes a message that requests a request name. The method of this instance is checked by the join manager, which determines the use of that dictionary to send the same message, regardless of it must access That database.
When data is obtained from multiple data sources, this mode provides dynamically changing the ability to access the database or table. It flexibly reduces the work of the same SQL code description over again for multiple databases, and can still access them.
Table Manager In a sense, the metadata is stored for the table, which is used to dynamically generate database queries when the metadata is applied to any table name. Basically, a Schema describes this mapping, whenever you access a database.
Example Implementation:
The table manager stores the table name in the dictionary structure. When the request is requested, the Dictionary structure is initialized when the table manager is initialized, and then the appropriate dictionary is accessed, and the table name is accessed according to the coupling manager.
When a domain object says:
Self class Table,
TableManager will return to the name of the table for class.
in conclusion:
• One advantage of the Table Manager is that when a table name is modified, only one place in the code needs to be modified;
Another benefit is that different names or views of different databases can be accessed with different names;
• Writing a table manager includes a mapping to interpret the tables and fields, which is not easy to develop or maintain.
Related or interactive mode:
• As long as there is a need to access the database, the persistence layer and the join manager will call the table manager;
• The SQL code description will use the table manager to isolate the developer and the database.
The table manager is a Singleton.
The table manager is actually just a way to describe the database structure with metadata;
The table manager can use a translator to complex mapping or use metadata for dynamic systems.
Known application:
• Illinois Department of Public Health Tots and Newborn Screening projects;
Many database systems use data dictionaries;
VisualWorks Objectlens uses a Spec [Foote & Yoder 98] to provide a table mapping in conjunction with SCHEMA.
Comprehensive discussion:
Now you have seen all the modes, you may ask, "How do I integrate with them?" All of these modes work together to provide a mechanism for persistent objects to map into the database. Figure 2 shows how the mode is interacting. The persistence layer provides a standard interface for the Crudation of the required persistent domain object, and the persistent layer is built using the SQL code description of the domain object to build the database call, when generating SQL code, persistence layer and table Manager interacts to get the correct database table name and field name. When you have returned data values from the database or write back the database, the attribute value must be mapped to the database field name, and vice versa, this is completed by the attribute mapping method. The property mapping method performs some types of conversions in SQL code generation. Attribute mappings and type mappings will happen when the persistence layer instantiates a new object. The persistence layer changes the value of an object to the specified database through the coupling manager. This change value is managed by the change manager; the join manager can interact with the table manager and determine which database is used. The persistence layer provides access to the transaction manager when the transaction is required. Figure 2 - Mode interaction map
A class scenario (see Figure 3) shows how the object interacts when the value is in our example. A Name class can request Load that will be forwarded to its superclass PersistentObject. It will get a join from ConnectionManager, then PersistentObject will generate SQL, to complete this, he needs to request this SQL to Name, and get some table name mapping from TableManager, once a SQL is generated, a Database Component call will return the result set, then, then, To create a new Name object returned from the database, assign each field of this row to a specific object property, during the mapping database value to the object properties, the database type will be converted to the corresponding Object type. Once completed, PersistentObject returns a collection of Name objects that have been created.
Figure 3 - Class interaction
reference
[AMBLER 97]
Scott W. Ambler. Mapping object to rate data. URL:
http: // www.ambysoft.com/mappingObjects.pdf
[Beck 97]
Kent Beck. SmallTalk Best Practice Patterns, Prentice Hall Ptr,
Upper saddle River
,
NJ
1997.
[BRANT &
Yoder 96]
John Brant and Joseph Yoder. "Reports" "Collected Papers from the plop '96 and europlop '96 conference, Technical Report # wuck-97-07,
Dept. of computer science
,
Washington
University Department of Computer Science, February 1997. URL:
Http://www.cs.wustl.edu/~schmidt/plop-96/yoder.ps.gz.
[BMRSS 96]
Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, Michael Stal. Pattern-Oriented Software Architecture: a System of Patterns, John Wiley and Sons Ltd.,
CHICHESTER,
UK
1996.
[Foote &
Yoder 96]
Brian Foote & Joseph Yoder. "Evolution, Architecture, and Metamorphosis," Pattern Languages of Program Design 2, John M. Vlissides, James O. Coplien, and Norman L. Kerth, eds., Addison-Wesley, Reading, MA., 1996.
[Brown &
WhiteNack 96]
Kyle Brown & Bruce Whitenack "Crossing Chasms: A Pattern Language for Object-RDBMS Integration,". Pattern Languages of Program Design 2, John M. Vlissides, James O. Coplien, and Norman L. Kerth, eds, Addison-Wesley,. Reading, Ma., 1996.
[Foote &
Yoder 98]
Brian footata, "submitted to plop '98. URL: http://wwwcat.ncsa.uiuc.edu/~yoder/research/metadata.
[Fowler 97-1]
Martin Fowler. Analysis Patterns: Reusable Object Models, Addison Wesley, 1997.
[Fowler 97-2]
Martin Fowler. DEALING WITH ROLES, Proceedings of PLOP '97,
Monticello
, IL, OCTOBER
1997. URL: http://www.aw.com/cp/roles2-1.html.
[GHJV 95]
Eric Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley,
Reading
,
MA
1995.
[Gemstone 96]
Gemstone Systems, Inc. Gembuilder for VisualWorks, Version 5. July 1996. URL:
http://www.gemstone.com/products/gbs.htm.
[GemConn 96]
Gemstone Systems, Inc. GemConnect For VisualWorks, Version 5. July 1996. URL:
http://www.gemstone.com/products/gbs.htm.
[Keller 97-1]
Wolfgang Keller: Mapping Objects to Tables: a Pattern Language, in "Proceedings of the 1997 European Pattern Languages of Programming Conference,"
Irrsee
,
Germany
SIEMENS TECHNICAL REPORT 120 / SW1 / FB 1997.
[Keller 97-2]
Wolfgang Keller, JENS Coldewey: Relational Database Access Layers: a pattern language, in "Collected Papers from the plop'96 and europlop'96 conferences" Washington
University
, DEPARTMENT OF Computer Science, Technical Report WUCS 97-
07, February 1997.
[Keller 98-1]
Wolfgang Keller, JENS Coldewey: Accessing Relational Databases: a pattern
Language, In Robert Martin, Dirk Riehle, Frank Buschmann (EDS): Pattern Languages
Of Program Design 3. Addison-Wesley 1998.
[Keller 98-2]
Wolfgang Keller. "Object / RELATIONAL Access Layers - A Roadmap, Missing Links and
More patterns, "Submitted to EPLOP '98.
[OE 98]
IBM, Corporation. Object Extender for VisuaLage. 1998.
URL: http://www.software.ibm.com/ad/smalltalk/about/persFact.html.
ORfali &
HARKEY 98]
Robert ORfali & Dan Harkey. Client / Server Programming with java and {corba},
2nd Edition, John Wiley & Sons, 1998.
[OS 95]
Objectshare, Inc. VisualWorks User's Guide. 1998.
URL: http://www.objectshare.com/vw30abt.htm.
[Rsbmz 98]
Dirk Riehle, Wolf Siberski, Dirk Baeumer, Daniel Megert, & Heinz Zuellighoven.Serializer, in Robert Martin, Dirk Riehle, Frank Buschmann (Eds.): Pattern Languages of Program Design 3. Addison-Wesley 1998.
[Toplink 97-1]
Toplink Version 4.0 - A White Paper, 1997.
URL: http://www.objectpeople.com/.
[Toplink 97-2]
The Object People Inc .: Toplink Version 4.0 - User Manual, 1997.
[Va 98]
IBM, Corporation. Visualage Smalltalk. 1998.
URL: http://www.software.ibm.com/ad/smalltalk.
[Yoder &
Barcalow 97]
Joseph Yoder & Jeffrey Barcalow. "Security," Fourth Conference On Patterns
Languages of Programs (PLOP '97)
Monticello
,
Illinois
, September 1997. Technical report # wucs-97-34, Dept. of Computer Science, Washington University Department of Computer Science, September 1997.URL: http://www-cat.ncsa.uiuc.edu/~yoder/papers/ Patterns / # yoderbarcalow1997. [yoder 97]
Joseph Yoder. A Framework to Build Financial Models.
URL: http://www-cat.ncsa.uiuc.edu/ ~yoder/financial_framework.
[Yoder &
Wilson 98]
Joseph Yoder & Quince Wilson. A Framework for Persisting Objects To Relational Databases. URL: http://www-cat.ncsa.uiuc.edu/~yoder/research/Objectmappings.
[You 95]
Joseph Yoder & Quince Wilson. Mainstream Objects, An Analyzis.
URL: http://www-cat.ncsa.uiuc.edu/~yoder/research/Objectmappings.