Power-oriented power for table programming
--Butler Introduction
Original: http://www.javaworld.com/javaworld/jw-10-2004/jw-1018-butler.html
Summary
Since the object-oriented and three-layer structure, enterprise application designers have been trying to hide the specific structure of the database. This increases the complexity of the software, and forced developers have made many unnecessary hierarchies other than the underlying. This article describes a library-oriented library -Butler. BUTLER is based on JDBC, including many SWING components with data perceived ability, can greatly reduce the pressure of the underlying GUI in the enterprise client application.
When an object-oriented language starts an application in an enterprise application, how the designer encounters how the relationship model is converted into the pressure of the object model. Inside the object-oriented model, the data is packaged. However, the relationship model is reversed, and the data does not need to be hidden at all. It is believed that many designers think that if you use a relational database that you can't be avoided, they hide the business logic.
The dream for object-oriented developers is to have an object-oriented database. But this database is unable to get enough market share in market competition, and it is likely to not substituting relational databases. Recently, many developers, or even the object-oriented subjects, they have acknowledge that the relationship database is better than object-oriented data.
Although there are many advantages in relational database, many mainstream persistent frameworks (such as EJB, JDO, Hibernate) refuse to store objects in relational databases. All relational databases are composed of tables, columns, primary keys, foreign keys, records, and queries. But there is no mainstream product has an object model that meets these entities.
Another optional model, a table-oriented programming model, allows the application source code to know the real database structure, not to hide the database structure in the application's mapping layer. Many enterprise applications have a lot of CRUD (Create, Read, Update, delete). If the database structure is not hidden, developing crud features will be simple.
Some people think that the object model does not have to be consistent with the database structure, so that business logic does not need to change even when the database structure changes. But these people ignore many business logics to be implemented on the relational database Schema, so it is accurately that the change database SCHEMA will also change business logic.
The result of the real structure of the hidden relational database is to use an additional abstraction layer. Tables, columns and foreign keys, etc. must be mapped to classes, attributes, and associations. In many ways, you need to make a class for each table, make each column, and use the association to represent the foreign key. In addition, SQL is also re-transformed (such as Hibernate query language HQL, JDO-QL, EJB-QL, etc.). Why add these extra levels? These levels provide little characteristics, but it has increased complexity.
The biggest advantage for forming a table-oriented is to provide the ability to create data to perceive the GUI components. If you are implementing an application used to reality and / or update data in a database, JTables, JCOBOXES, and JFORMATTEDTEXTFIELDS Connection Database can save a lot of development time. For web applications, data perceived tag libraries can also accelerate development. Any mainstream persistent framework is more than the data-oriented framework for the data perceived assembly.
In the object-oriented world, many views oppose data perception components. A common point is that the GUI and databases cannot share the same structure. Some client applications are indeed, but for clients facing Crud, data-sensing components can save a lot of development time. Just because the data perceived component cannot be used in all applications, it is not a reason why it is sufficient to oppose it.
Another worries for developers are fearful to use data-sensing components to detrimentally to specific databases and IDEs. Indeed, some databases and IDE developers have created a GUI component library bound to a specific database and IDE. But if you have a component library with JDBC and ANSI SQL-92 syntax, this library is not related to providers.
In fact, the importance of data perceived components is slowly attached to the object-oriented world. Even Sun has realized this need from the open source program JDESKTOP NetWork Components. This article is to discuss an existing table-oriented persistent framework --Butler.
l object model
Butler has a series of classes dedicated to describe the database SCHEMA structure:
u table: Description Table Structure
u Column: Columns in the table
u foreignkey: Foreign key between two tables.
These classes are only used to represent the structure of the database (DDL, data description language). When reading and writing from the database, the value object is also required. What can be recorded in a representative table that is more natural than a Java class called Record?
l acquisition record
Through the value of the primary key, you can get a record, you can call the FindBypk () method in the instance of the table, replacing the use of Select from the desired table. The parameter of the method is the value of the primary key. E.g:
RECORD REC = TableRef.FindBypk ("ABC123");
If you want to get all the records, just call the FindAll () method, this method returns a list of records instead of a separate record.
For other complex queries, you must use the Query class, which represents a SQL in a SQL declaration. Many mainstream persistent frameworks are represented by the string. In many ways, representing the character string makes the code compact, but it also brings some shortcomings. Use objects and methods to construct queries more secure. A large number of errors will be discovered when compiled, rather than causing runtime errors. The identity of the IDE, such as the code is automated, and the programmer will use the Java language to build a query than using the string.
The query in the Butler always has a starting table (or a primary table), which represents the source of the record query. It can also be combined with other tables. The result will also be a list of records from the starting table. However, each record from the starting table and the associated table are recorded, which can be accessed via the getRelatedRecord () and getReledRecords () methods. This provides a large difference (or advantage) relative to JDBC, in JDBC, the results of the query are always two-dimensional. By recording a layered, it can also be updated or simple to perform more complex result processing.
Butler uses the Filter subclass to specify the record you need to select. For example, whether the Equalsfilter is simple and compared to whether the value is the same as the column. Filter expression is used to replace all logical operators you in the SQL declaration.
Specifies the order sequence to use the addsortcritera () method. This corresponds to the Order By clause in SQL.
To put all the things, then a simple query will be:
Query Q = Ordertable.createQuery ();
Q. Join (OrderDetailTable);
q.addColumn (Ordertable.getColumn ("ORDERID");
q.addColumn (Ordertable.getColumn ("ORDERDATE"));
Q.AddColumn (ORDERDETAELTABLE.GETCOLUMN ("ProductID"));
q.addColumn (ORDERDETAILTABLE.GETCOLUMN ("Quantity"));
Equalsfilter filter;
Filter = New Equalsfilter (Ordertable.getColumn ("Customerid"))
Q.Setfilter (filter);
q.addsortcritera (ORDERTABLE.GETCOLUMN); QueryInstance Qi = q.createInstance ();
Filter.Populate (QI, "BLONP");
Recordlist resclist = qi.run ();
Butler provides built-in XML support for many classes. A query result can be converted into the following XML format:
record>
record>
records>
record>
records>
This is very useful for generating reports, which can be easily converted into formatted objects used to generate a PDF document, and the hierarchical structure of the query results (relative two-dimensional structure) make it possible.
l Update record
In Butler, updating database records is very simple. You only need to call the SET () method of the record instance, and use the column name and value as the parameters to update the columns you need. Then call the save () method:
OrderRec.Set ("ORDERDATE", ORDERDATE);
OrderRec.Set ("ShippingDate", ShippingDate;
ORDERREC.SAVE ();
First call the addRecord () method of the corresponding table object, then set the value of the column and save the record:
OrderRec = OrdertAb.addRecord ();
ORDERREC.SET ("ORDERID", New Integer (123));
OrderRec.Set ("ORDERDATE", ORDERDATE);
ORDERREC.SAVE ();
Deleting records are equally simple. Just call the delete () method of the recording object. If you want to delete multiple records, you need to use the DeleteQuery class. It is very similar to the Query class, you need to specify a file to represent the record you need to delete:
DELETEQ = Ordertab.createDeleteQuery ();
Filter = New Equalsfilter (Ordertable.getColumn ("Customerid");
Deleteq.setfilter (Filter);
QueryInstance Qi = Q.CreateInstance ();
Filter.Populate (QI, "BLONP");
Qi.run ();
The Butler also provides a function of registering a record monitoring. You can register a RecordListener for each update, insert, delete, and later, the corresponding event method will be called. l generator
As in the example above, the column name and table name are given in the form of a string. Programmers may type errors, which will cause an error. To prevent this, Butler can use the generator class to generate Table and Record subclasses containing the GET and SET methods of each column.
The generator can also be used in another form. The generated subclass also includes structural information of the database. Butler does not have to get metadata for data at runtime through JDBC, which proves to be very time consuming for some databases. The original data is obtained when it is generated. If you don't have to generate a subclass, you can also generate an XML file that describes the database structure.
l Data type
So far, this article has described simple ways to generate JDBC calls. But Butler also includes features other than JDBC.
The database-centric app always contains the verification and formatting of the data. When the user enters the data, check must be verified before depositing into the database. It must be formatted before the data is provided to the user.
In Butler, the columns in each table can be associated with a DataType object. DataType can check and format the value of the column. Butler's DataType implementation for strings, numeric values, and dates. However, programmers can also write personalized DataType classes to process personalized data types, such as phone numbers, addresses, and even big data objects such as images.
The Butler class described above can be regarded as a simplified and enhanced database programming, while a layer added on the JDBC. Use these classes that do not have to change the structure of the application. Can be used in any JDBC.
Below I will introduce the data aware of the SWING component. Use these classes to change the structure of the application, but the database structure will no longer be invisible with the client.
l Swing component
In client applications in the database as core, you will find examples of many JTables and database tables. It is often costly to achieve such a table. But use the RecordListTable class to save a lot of time. Programmers only need to tell what tables and columns need to be displayed in the database, and assign RecordList to RecordListTable. Columns in related records (multi-to-one relationship) can also be displayed. RecordListTable allows updates, insert, and delete records. E.g:
Reclisttable = new recordlistTable (ORDERTAB);
RECLISTTABLE.ADDCOLUMN (ORDERTAB.GETCOLUMN ("ORDERID"));
RECLISTTABLE.ADDCOLUMN (Ordertab.GetColumn ("Customerid");
Reclisttable.addColumn (Ordertab.GetForeignkey ("fk_orders_customers"),
CustomERTAB.GETCOLUMN ("CompanyName"));
ReclistTable.RecordListSelected (Orders);
If the content of the record needs to edit the detailed content outside of RecordListTable, you can use the RecordEditor class. This class provides a panel for editing records, providing editing components for each column (or specified columns) in the table.
RecordEditor implements an ActionListener interface, and the new command tells RecordEditor adds a new record, saved the current record. E.g:
Editor = New RecordEdeditor (Ordertab);
Editor.Add (OrderTab.getColumn ("ORDERID"); editor.add (Ordertab.getColumn ("ORDERDATE");
SaveButton = New JButton ("Save");
SaveButton.SetActionCommand ("Save");
SaveButton.AddActionListener (Editor);
For personalized hierarchy, RecordController can be used instead of RecordEditor. The invisible components will be automatically generated. RecordController has a factory approach to generate editing components. Programmers only need to put these components in the required location:
Controller = New RecordController (ORDERTAB);
ValueEditor Editor;
Column col = Ordertab.getColumn ("ORDERDATE");
Editor = Controller.createColumn (COL)
Panel.Add (Editor);
For RecordEditor, RecordControl's work mode is similar to RecordSelectionListener.
In many clients, the list of records (RecordListTable), when the line (record) is selected, the record should be displayed in a detailed view (RecordEditor or RecordController). In order to add this function in Butler, just register with RecordEdSelectionListener in the formner of RecordSelectionListener:
RecordListTable.AddRecordListTable (RecordEditor);
In many clients, users need to first select the ability of the records he needs to display or edit. In Butler, you can use QueryPanel to add this capability. QueryPanel will generate a corresponding GUI after getting Query, which can enter the value obtained in the filter. If the result needs to be displayed in RecordListTable, just register RecordListTable in the formner of RecordSelectionListener to QueryPanel:
Query = Ordertab.createQuery ();
Query.setfilter (NEW Equalsfilter)))))));
Panel = new querypanel (query);
Reclisttable = new recordlistTable (ORDERTAB);
Panel.addRecordSelectionListener (ReclistTable)
If a personalized level is required, you can use the QueryController corresponding to QueryPanel.
What is introduced above is some commonly used data perception components, if you observe a business client application, you will find the following mode in many pictures: Some of the application screen is used to enter the query parameter and query button (QueryPanel) The following is a list or table (RECORDLISTTABLE) used to display query results, then below, is a detailed view of a discounted number of pop-up windows (Recordeditor).
If you need to create a client like this, you don't need a personalized level, you don't have to manually design these components. Instead, use the SimpleForm class to create a screen of such a structure, just a few lines of code.
l Summary This article describes non-mainstream database programming solutions. This scenario is similar to object-oriented database programming. But the biggest difference is that Butler utilizes an object-oriented full force to make relationship databases and object-oriented programming languages do not coordinate.
Related Website:
Butler Database Frame: http://butler.sourceforge.net
For more information on table programming: http://www.geocities.com/tablizer/top.htm
(The first translation, the shortcomings, Haihan .cqucyf @ 263.net)