How to develop database applications with JDO
(The copyright of this article is author himself, welcome to reprint, but must indicate the source and original author)
This article describes how to use Sun's latest "Java Data Objects" specification for database-based simple applications, so that readers have a direct sense of understanding of JDO, which is a more in-depth development, and also hope Throwing bricks, let more experienced masters participate in promoting JDO process, providing more exciting articles for readers!
1. What is the sacredness of JDO? Is it the Turn on ADO?
This section can be a little more often talking about the readers who are familiar with JDO, and a bunch of garbage is worse than recycling. However, I think that these are truth, feeling, no spit, may also have some help for newcomers, at least one thing should be resonated. So, please skip this section directly.
1.1. Java advantages
Since the world of Java language, its almost full of objects and liberation of the automatic garbage collection mechanism of our programmers show us a new development world: the original program can also write this! I have used a few years C , and the pointer inside is simply ambiguous! I still remember that some variables like "*** lpszinfomapofmap" have been used. It is a pointer to the pointer of the pointer. It is not easy to accurately grasp this in the encoding process. Let alone remember to release each The memory occupied and cannot be released multiple times (strictly said that it should be done with the memory applied and only once)! I still admire the clear mind in the year, but in the debugging process, "Accessviolation" and "Nullpointer" mistakes in the debugging process have made me all night! (One time to debug a problem, I have a lot in the second day.) After C , I have used Delphi for more than three years, and the program code is very understanding, and it is easy to maintain, but the pointer is still the pain forever in the chest! Until Java, I will get away from the bitter sea, enter the era of "development according to the speed of thinking" ...
When Java's speed is greatly improved, we start using it to write database applications, but to tell the truth, Java's database is still very raw, the database components in the graphical interface are very difficult, plus the main written is Web applications, only JDBC interfaces are available. Lift JDBC, I believe that many readers will have this impression: there are too many concepts, strict but trouble, especially the release of resources is also a big problem. It's a mess with Microsoft's ADO, it's particularly bad.
1.2. Object packaging technology, 100 pairs? Is the magical dance?
Thus, from the principle of standardized development, we start writing your own JavaBean to pack data objects, making data objects, avoiding too many places involving JDBC operations. But some problems also come: the flexibility is not enough, the interface is dead, the performance is low, which makes me worry. So, "the gentleman is not different, good and fake is also in the object", and I also go online to find "technical support"! Soon, it was actually discovered "CASTOR JDO", a special OQL dedicated to data packaging, DMG standard OQL as a query language, convenient and easy to understand, much better than SQL. This allows me to enjoy the benefits of "object-oriented database development", "the effect is good, affordable!".
However, the good view is not long, some inherent bugs in Castor affect stability, and this free product update is too slow, and has not been resolved. I have to give up. "Doubted see tears in their eyes, even Yuning choke"! How to do? You know, how can you endure the life that can only be taken by the person who is extravagant, people who are extravagant, those who eat meat! It is still uncommon to "Party B". For us, using JDBC original call seems to be difficult to swallow, and then use JavaBean packaging and a little return, so I started the online search history. Mr. Yu Qiuyu has "cultural and bitter travel", this is also "programming bitter travel", huh, huh, hilarious. From the online information, my experience is also a common experience of many Java development colleagues. Whether domestic or abroad, from the actual situation, foreign research is more in-depth, at least from the information you can found online. It is the case. The United States has begun to study object-oriented database ODBMS from the 1980s. There are currently some forming products, such as Versant's Versant database, FastObjects's FastObjects T7 database, and other companies such as ObjectStore, such as other relative market share. Products, of course, there are no shortcomings such as orient, etc. Overall, although ODBMS has an object-oriented advantage, because of historical reasons, it is always in the lower wind in the competition with the relational database RDBMS, and the application based on RDBMS is still mostly, and therefore, some Object-Relational maps appear. Tool, the Cast mentioned earlier is a tool in recent years. In fact, there are some mature, stable commercial products, such as toplink acquired by Oracle, WEBGAIN, which is acquired by BEA , More famous Cocobase, and more.
I also understand the product like Toplink, the function is powerful, performance, and stability have advantages, however, their equally powerful prices and weird APIs make me step. I am very worried that it is locked in a product, can't get out, well known, Java gives us a feeling of freedom, freedom, will always attract people.
Where is the way out? JDO is in front of my eyes.
1.3. JDO surface, don't think is ADO
JDO Since 1999, JDO has submitted an outline from some experienced developers who often write database object mappings, and they have conducted a lot of database processing and objective packaging in long-term object-oriented development, finally, a variety of diverse Packaging methods have caused many compatibility issues. So some major development teams jointly, with Sun as leading sheep, developed JDO specifications. Its goal is not to replace JDBC or EJB, but packaged on the JDBC, and can also make EJB's underlying (CMP), simplify the J2EE server provider. JDO is primarily for small and medium-sized projects, but with the product provider (Vendors) gives more and more features, such as distributed synchronous control, JDO's role is growing. JDO specification under the leadership of Sun's experienced Craig Russel, after three years of discussion, finally formed a first edition in April 2002. The latest version is version 1.0.1, can be seen in http://access1.sun.com/jdo/. (Everyone should know that Java's standardization time is generally a long, because it is too open, anyone can express it, people who participate in the formulation of norms must consider these opinions) ADO is Microsoft's data access component collection, believe a lot Friends who wrote the ASP page database application are impressed, fast, faulty is strong, but the scalability does not dare to compliment, how many years have been written, can't surpass. Some readers who have just contacted JDO may make JDOs with ADO, thinking is the Java version of ADO, that is wrong, both the wind is not blind, can be said that it is not a grade. Fortunately, Microsoft did not register "XDO" abbreviations into trademarks or patents, otherwise the two big heads have to fight the lawsuit, hey, I like to watch the lively, playing it is equally exciting!
1.4. JDO product introduction
JDO Specifications have been launched in April 2002, there have been many special products. Of course, these products have followed the JDO specification and will not affect the portability of the JDO application you write. The following is listed in my impression of each product: (See Section 6 Reference Article: "JDO Resource Introduction")
Godfather: Lido (Libelis, France), I am mainly through Lido products, it briefly solves the use and advantages of JDO in a graphic tutorial in March 2002. This tutorial can be downloaded here: http://www.objectWeb.org/conference/jdo.pdf. Lido's features are large, support file database, RDBMS, ODBMS, and even XML databases. But the configuration is more troublesome. The latest version is 2.0RC. Overlord: Kodojdo (US Solarmetrics) Kodo is one of JDO's medium-sized pillars. When JDO1.0 has not passed, it is a relatively mature product, which is characterized by focusing on performance and stability, the latest version is 2.5 .0, is the most customer products. Best Missionary: JDogenie (South Africa HemSphere) This is the most recommended product, the latest version is 1.4.7, the performance is good, the stability needs to be verified, but it has a biggest feature: good integration, most Yi Xue, its company's CTO David Tinker is also a young man who knows people. It adopted a lot of netizens to improve the product, mainly in configuration, with a special graphical interface tool, can be configured, database generation , Object query, etc. very practical. highly recommended! Everyone 秀: JRELAY (Germany Objectindustries) This is also a more early product, and a GUI tool is used for configuration. When the tool is still relatively convenient, but more than a year, it seems that there is no progress, The latest version is 2.0, I tried for a while, I will not follow up. Two-faceted: Frontiersuite for JDO (US Objectfrontier) This product is with Jrelay, Kodo, which is an early JDO three sword passenger, called it for two displays because it is also developed and reverse development. Its features are relatively convenient in reverse engineering (from the table structure to generate data classes), and the combination of UML is also very strong, but the configuration is complex when it is actually running. At the beginning, the company has bought a copy with 10%, but I didn't care at the time. If God gives me a chance ... Free lunch: TJDO (a group of cross-borders) This is a free product formed by adding some extension features on the basis of Reference Implementation in Sun, currently The latest version is 2.0beta3, but progress is slow, this version has already had a few months without further updates. These are the more representative products I have used, as well as many commercial products, as well as some other or non-specific free JDO products (such as xorm, ojb, etc.), here no longer list, interested Readers can go to http://www.jdokecentral.com/ to learn more.
2. Which hero is jdogenie?
As mentioned earlier, JDogenie is a commercial product in South Africa. Don't underestimate South Africans, they have a lot of income! Of course, technology is also good. If the reader has done UML modeling and design, you may know the product of Together Control Center, that is, a UML design tool recently acquired by Borland. JDogenie's produced company HEMSphere is the South African distributor and partner of Together. Speaking of this, the plug-in question, IBM acquires Rational, Borland acquires together, Sun acquires Describeuml, an IDE UML war will be staged.
Ok, the book is biography, JDogenie is my current product, the reason is easy to use, simple to play, and friends who want to learn JDO is the most suitable! It has a configuration tool for a graphical interface, which is very convenient to perform data table mapping, SQL operation, JDOQL query, etc. The web server that uses JDogenie can also be monitored by this graphics tool. You can find out which query fees are more than the number of times, which helps database optimization adjustment.
As the saying goes, I will not be as good as I see, let's give a few pictures first, I have to add addiction:
Console interface (Workbench):
The following content is to introduce JDO's development processes with JDogenie, so you need to download JDogenie first:
First go to http://www.hemtech.co.za/jdo/download.html to download the latest version (this article is 1.4.7), then click the "Obtain Evaluation License" link on the page to get a month's trial license (Will it be too little one month? Rest assured, the company will post a new License when it is expired). You need to fill in some information when you get the trial license.
3. What do we want to do - demand description
This section mainly describes the functions of the applications that will be made herein. This application is very simple. It is a functional subset extracted in a "Bank Credit Card Trading System" proposed by netizens, and has made a simplified and functional change in order to reflect the characteristics of JDO, mainly to complete the following functions. :
Enter credit card information. Credit card information includes the following information:
Card Number (Automatic Generation) Cardholder Name Identity Document Number Address Contact Phone Account Date (Automatic Generation) Account Overhead Current Balance (Automatic Calculation) Allowed Bode Browse Credit Card Information Browse All Credit Card Information Transaction Swipes A transaction for credit cards, need Entroy the following information: The card number, the transaction amount If the transaction amount is exceeded, the prompt cannot be completed. If the transaction is successful, the system automatically records the transaction time deposit entry card number and deposit query overdraft report to see all overdraft credit card query transaction details can query all transaction information according to the cardholder ID number
The above is the function of the entire application, very simple, if we use JDBC, we will immediately think of the first two tables: credit card table and trading table, the two are associated with the card number, and then these functions are a bunch of SQL and these two tables. It is hodgepodge. However, we must use JDO now, how to do it? please watch the following part……
4. Development process
Just look at the skills of the above functional demand, JDogenie should also down, if not, I have installed an ADSL! (Don't guess, I am not a telecommunications staff! I only have envy ...). The process of developing JDO is roughly as follows:
First write the original data object model code and compile into .class files, these data objects are called the original object (Pojo, Plain Old Java Objects) and write a stored descriptor metadata, also known as metadata, indicating some of the storage-related settings, For example, which classes need to be saved to the database, which fields in each class need to be read priority, which field delays (LazyLoad), etc., this metadata must be placed in the classpath, the extension is ".jdo". The writing of Metadata can generally be done by tools, such as the workbench of JDogen, can be easily done. After writing a descriptor, the translational .CLASS file is translated according to the description of the metadata, allowing these class code JDO, which can be called in other code. The application code is mainly through the JDO Storage Manager (Javax.jdo.PersistenceManager, after referred to as PM) to complete an increase, deletion, modification, query, etc. of data objects.
The schematic is as follows (from Versant's JDO tutorial): where XML config is * .jdo
4.1. How to model
When we turn your mind OO, the above needs becomes several basic objects in our mind: credit card and transaction records, and some operations for these objects. (In fact, our minds are the object of the basic objective world. It should be said that it is OO, or how can the brain be some of the intestines of the "O" "?: D)
For a brief, we have the modeling of our models without large UML tools like Rose or Together. In Duke or Quake, sometimes rifles, even chainsaw, will become the most effective and most direct killing tool, and the pistol in CS is often surprising. Now, on the battlefield developed by the program, we offer the most original tools: Notepad! I believe that no one will use it. Simply said that the following content is directly used as an example of modeling.
First, we analyze the class of credit card, very simple, add the fields listed as the property to the class, this and the process of the built-in form is not much, the difference is not much, and the relationship between the objects will have different).
Package Credit.system;
Import java.util.date;
Public class creditcard {
String name; // Name
String address; // address
String idcard; // ID number
String phone; // Phone
Date CreateTime; // Account Opening Date
Date lasttransactionTime; // Date of the most recent transactions
Float initialbalance; // accounting amount
Float balance; // current balance
Float allowoverdraft; // allows for overdrawn
}
Hey, what is wrong? Yes, your eyes are really sharp! "I have made so many years of database application development, never have seen the table without keywords, I have never seen such a class without identification fields! Where is the card number ?? !!" Yes, where is the card number? Who dares to use without a card number? Take the morning floor to cover home!
Don't worry, here, give you a concept of JDO about object identity: ID is actually just an object's unique tag, a bit like an object's memory address, for a traditional database, is a recorded primary key. JDO believes that if the keyword is just the uniqueness of an object, it is not necessary to participate in business logic (such as calculation), you do not have to put it in the class code, this unique maintenance only needs to be by JDO middleware (Implementation Decomposition, this object identification is called DataStore Identity, general implementation is to use increment integers; if the identity is also involved in business logic (if the primary key is created, it is used to sort or range), you can appear in class code. This object identification is called Application Identity. For these concepts, please refer to "JDO development help in this article" JDO development help. "
In the above credit card class, we believe that the credit card number is just a logic of the credit card, so we use the Datastore Identity to make the uniqueness of the identity to maintained by JDO products, as an object in memory No need to specify in the program code, but is maintained by JVM.
Hey, what is wrong? Yes, your eyes are still so sharp! "Your credit card is not identified, then how do my transaction records to associate it ?? !!"
Yes, the data object I have written before I wrote, and there is also a primary key attribute. Another object is associated with this object through a same type of property. Now that your primary key attribute is gone, how do I get related? Nothing?
This question is very good, it is also very typical (note, it is very typical, not "non-typical").
However, people who ask this question should be the experienced developers, data sheets, primary keys, foreign key associations that have been written for many years. It has been deep into the mind, even if it turns into Java classes, the main key foreign key is still the soul. This method can be described as "replacing the soup without changing the medicine", there is no substantial change, such an object model does not reflect the relationship between the object, can only be grasped by the program. To be honest, I first did it to do the object packaging. I'm so embarrassed, now let's make a big bigger, then open a little, look at the concept of JDO: If there is a relationship between the object, only need to directly Relationship The object declares that it is a property (or a collection of attributes).
In this way, our transaction records are written as the following:
Package Credit.system;
Import java.util.date;
Public class transactionRecord {
Date CreateTime; // Transaction Time
FLOAT AMOUNT; / / Transaction amount
String Note; // Remarks
CreditCard Card; // Credit Card
}
In this class, we see that there is no "credit card number" attribute, which is replaced by a credit card object "Card", so we will not need to call a query statement when you get the relevant credit card through the transaction record. The credit card object is obtained, just simply read the CARD attribute of this transaction record object. This is also one of the object-oriented conveniences. With these two classes, our "Bank Credit Card Trading System" foundation is also set.
4.2. If you are afraid of chaos ... recommended code specification
I remember to have heard a sentence before, "The world's eternal truth is there is no eternal truth", here, I also want to say: The most perfect solution in the program is not to think that there is the most perfect solution. (What is it, simply understand. Oh, I can't understand myself).
What I want to say is: JDO has certain restrictions, can't let you expand your wings (note, "shark fin"), sway in the object-oriented sea. Why will JDO limit? Because its principle is to make a certain transformation of your class code, insert some of the management and maintenance code involved in JDO into class code, so your call code may need to make some changes. These are JDO restrictions. Simply put, if you get a TransactionRecord type object TR, you want to obtain a credit card object involved, it is not recommended to get the following code: Tr.Card, but it is recommended to declare this property as private, then give it out A getter is obtained (GetCard ()), that is, the JavaBean properties package. In this way, our two data classes will become the following:
CreditCard.java:
Package Credit.system;
Import java.util.date;
Public class creditcard {
String name; // Name
String address; // address
String idcard; // ID number
String phone; // Phone
Date CreateTime; // Account Opening Date
Date lasttransactiontime; // Time for the most recent transactions
Float initialbalance; // accounting amount
Float balance; // current balance
Float allowoverdraft; // allows for overdrawn
Public String Tostring () {Return Credit Card: Balance = " Balance ", cardholder = " Name ", ID number = " IDCARD ", phone = " phone;}
Public void setname (String value) {name = value;
Public string getname () {return name;}
Public void setaddress (string value) {address = value;}
Public string getaddress () {return address;}
Public void setidcard (string value) {IDCARD = value;
Public string getidcard () {return IDcard;}
Public void setphone {phone = value;
Public string getphone () {return phone;} public void setcreatetime (date value) {createtime = value;
Public Date getcreatetime () {return createtime;}
Public void setLastTransactionTime (date value) {LastTransActionTime = value;}
Public Date getLastTransActionTime () {Return LastTransActionTime;}
Public void setinitialbalance (float value) {initialbalance = value;}
Public float getinitialbalance () {returnin initialbalance;
Public void setbalance (float value) {balance = value;
Public float getBalance () {return balance;}
Public void setAllowoverDraft (float value) {allowoverdraft = value;}
Public float getAllowoverDraft () {returnous allowoverdraft;
}
TransactionRecord.java:
Package Credit.system;
Import java.util.date;
Public class transactionRecord {
Date CreateTime; // Transaction Time
FLOAT AMOUNT; / / Transaction amount
String Note; // Remarks
CreditCard Card; // Credit Card
Public string toString () {return "transaction record: cardholder =" card.name ", ID number =" card.idcard
", Transaction amount =" Amount ", time =" CreateTime;}
Public void setcreatetime (date value) {createtime = value;}
Public Date getcreatetime () {return createtime;}
Public void setamount (float value) {amount = value;
Public float getamount () {returnon
Public void setnote (string value) {Note = Value;
Public string getnote () {return Note;}
Public void setcard (creditcard value) {card = value;
Public Creditcard getCard () {returnad;
}
In fact, these adds Getter and Setter have a lot of tools to help, such as JBuilder, or together, or even the smaller and fine free tool GEL!
Such a proposal to package private attributes in the accessor, generally most Java developers are still acceptable.
4.3. Edit Metadata: System.jdo
This process, we can complete it through the graphics tools with JDogenie. After we compile the above two classes, we open the JDogenie's Workbench, which is running JDogenie1.4.7 and unpacking /workbench.bat, if it is running Workbench.sh under UNIX or Linux. Note You require you to set an environment variable in advance: Java_home, pointing to the root directory of the JDK installed (not a bin directory).
We create a new project (File -> New Project), select the root directory where the previous compiled class code is located (hereinafter referred to as ClassPath, two .class files should be in the current / system / subdirectory of this directory) Store this Project, because this Project is actually a configuration file (note is not .jdo file), generally contain some JDO products related information, such as opening some extensions, how much is the license number, this file is running is needed. We chose a Project name: Creditsys, JDogenie saved this project as a file called "Creditsys.jdogenie" in ClassPath.
Let's set the database first, in order to ensure practicality, we choose MySQL as the underlying database, install the mysql process is simple, download version 4.0.13 from the MySQL website, install it into the system, then start the mysql service. We will use the "TEST" database automatically generated after it installed as the database of this article.
We also need to download the JDBC driver on the MySQL website: The version number is 3.0.7. After downloading, the mysql.jar file in its zip package is solved in a certain directory.
Set the interface of the database as follows:
After configuring the database, you can test if the connection is normal. Maybe you will see a JDBC driver that can't find MySQL, it doesn't matter. We click OK directly, go to the Project property configuration interface, where the JDBC driver is added, and then it is back to test the connection.
The Project property configuration interface basically doesn't need to be set, as long as you do two must be configured:
Add MySQL's JDBC driver to ClassPath Add the root directory of our class code to ClassPath
The interface is as follows:
After clicking "OK", we arrived at the main window. In the main window, we can work in Metadata. We join the two data classes to metadata by menu meta-> add classes, indicating that these two classes are required to be stored. The rest of the data sheet structure, etc., all of us have left to JDogenie. During the addition of the data class, you need to create a metadata file. According to JDO standards, we only need to create a "system.jdo" in the ClassPath root directory. The interface after joining the data class is as follows:
Automatically generated metadata file system.jdo content is very simple, in fact, it is not difficult to write directly:
XML Version = "1.0" encoding = "UTF-8"?>
jdo>
However, if the class is more, it is more complicated between the relationship, it is best to complete the tools, so as to avoid grammar and semantic errors, unless you have experienced.
After that, we select the Build -> Recreate Schema of the menu to create the appropriate database. The table structure of the database is automatically generated. If you have objection to some of the table names or field names or field lengths, you can customize in the main window. Here is the concise and concise, all of which are automatically generated. If you want to see the data structure before you build a table, you can choose the menu "Build -> View Schema" preview the generated table structure SQL code:
- credit.system.creditcard
CREATE TABLE CREDIT_CARD
Credit_card_id integer NOT NULL, -
Address Varchar (255), - Address
Allow_over_draft float, - AllowoverDraft
Balance Float, - Balance
Create_time DateTime, - CreateTime
IDCARD VARCHAR (255), - Idcard
Initial_balance float, - InitialBalance
Last_Transaction_Time DateTime, - LastTransActionTime
NME varchar (255), - Name
Phone varchar (255), - Phone
JDO_VERSION SMALLINT NOT NULL,
ConsTRAINT PK_CREDIT_CARD PRIMARY Key (CREDIT_CARD_ID)
.) TYPE = INNODB;
- Za.co.hemtech.jdo.server.jdbc.sql.HighlowjdbcKeyGenerator
Create Table JDO_KEYGEN
Table_name varchar (64) Not null,
Last_used_id integer NOT NULL,
ConsTRAINT PK_JDO_KEYGEN PRIMARY Key (Table_name)
.) TYPE = INNODB;
- Credit.System.transactionRecord
Create Table Transaction_Record
Transaction_record_id INTEGER NOT NULL, -
Amount Float, - Amount
Credit_Card_ID Integer, - Card
Create_time DateTime, - CreateTime
Note Varchar (255), - Note
JDO_VERSION SMALLINT NOT NULL,
ConsTRAINT PK_TRANSACTION_RECORD PRIMARY Key (Transaction_Record_ID) TYPE = InnoDB;
Next, we save this Project, which is written to "Creditsys.jdogenie". Below we can continue to develop, that is, all of our data package work is completed, and you can enjoy the automatic maintenance of the automatic maintenance of the JDO and the benefits of the object-oriented JDOQL query language.
JDogenie1.4.7 has a benefit that its new UML class diagram function is simple and clearly given the relationship between the data classes, which is very useful for understanding the data model of others. Select menu "Meta -> Diagrams", add all classes to the figure, you can see the data model in this article:
If the class is more, you may have a cross section, which requires us to adjust the location of each class, do minimize cross. A complicated class diagram demonstration is as follows (not adjusted):
4.4. Enhance our data object class code
After the configuration information is written, Metadata is also generated, the following is to enhance our compilation-generated class code with JDogenie class code enhancer. Here, we wrote a ANT script to complete these troublesome work because we need to configure some ClassPath, JDO file path.
This Ant script is saved in our project root directory, named "build.xml":
XML Version = "1.0" encoding = "GB2312"?>
path>
delete>
target>
target>
target>
provject>
In this way, when we need to enhance class code, in the DOS box, run "Ant" in the directory where build.xml is located, you can complete the enhancement process. Alternatively, you want to run the test program class Credit.System.main (later will be said), just run "Ant Run", this can solve the problem with the iDE similar to JBuilder.
4.5. Writing business logic: the task that can never avoid
Business logic, seeming to be mentioned in object-oriented programming, but what is business logic? Is it just to show yourself very deep, so the port closing is the business logic? There is indeed such a person, talking about the development of the analysis and design, out of mouth is "business logic", in fact, maybe they don't know what is business logic.
My personal understanding may not be very sufficient. I understand this: Collaboration between objects and storage in applications (ie, changes in the attributes) is business logic, generally reflected in some rules, such as: When new generation of transactions, the credit card The total number of transactions plus 1, plus the total number of systems in the system is 1. Rules like this are business logic, these are specific, tools that tools are automatically implemented, must be embodied in your own application code, whether as Java code, or as a database store, in short, must There is a code to reflect these business logic.
After using JDO to solve the problem of storage, we can write a tool class (independent of the data class containing the business logic method) to complete the functions described in the requirements. Note that the JDO API we used in the following code. The use of the specific API see "Java Data Objects Chapter 1 Translation" in the end of this article.
Before completing the first functional requirements, we build some basic code to integrate JDO. We write a tool class named "CRedit.system.main" (also known as a control class) to provide these basic methods:
Package Credit.system;
Import javax.jdo. *;
Import java.util. *;
Public class main {
Public static void main (string [] args) throws exception {
System.out.println ("Start Test Features ...");
}
/ **
* This method is dedicated to obtaining the core object of the JDO API: Storage Manager PersistenceManager * /
Public static persistenceManager getPersistenceManager () {
IF (PMF == NULL) {
Java.util.properties p = new java.util.properties ();
Try {
/ / Read configuration information from the configuration file
P.Load (main.class.getclassloader (). getResourceAsStream ("/ credits.jdogenie"));
} catch (ioException ex) {
Throw new runtimeException (ex);
}
PMF = JDOHELPER.GETPERSISISTENCEMANAGERFACTORY (P);
}
Return PMF.getPersistenceManager ();
}
Private static persistenceManagerFactory PMF;
}
In order to make our code can compile and run, we also need JDO's API package and JDogen's support pack, which are synthesized into the "jdogenie.jar" file under the LiB directory of JDogenie, and a JTA package It is also a JDogenie runtime, that is, JTA.jar under its lib directory. We copied these two JAR files into our project directory so as to classify the boundary with JDogenie's directory, in addition, you also need to put the "JDogenie.License" file in the jdogenie's license directory (that is, License files obtained through the mail. ), Put it in our classpath. Of course, you can also compress the license file and the JTA package into jdogenie.jar, I like this, so that the dependence on JDogenie is concentrated into a JAR file, which is convenient to switch between different JDO products (because I A application is usually working under different JDO products to ensure normative and compatibility).
4.5.1. Enter credit card information
In order to place a business logic method, we will use a static method in the Main class to complete these business functions. First, we write a method to complete the function of adding credit card information:
/ **
* Enter new credit cards, only need to enter the required information, and other information is automatically generated.
* @Return generated new credit card object
* @Throws IDCardDuplicatedException ID Duplicate, not allowing new cards
* /
Public Static Creditcard InputCard
String Name,
String address,
String IDCard,
String Phone,
Float Initialbalance,
Float allowoverdraft
) throws idcardduplicateDexception {
Creditcard cc = new creditcard ();
cc.setname (name);
Cc.Setaddress (address);
cc.setidcard (IDCARD);
Cc.SETPHONE (Phone);
Cc.setInitialBalance (InitialBalance);
Cc.setAllowoverDraft (allowoverdraft);
// The following is the information automatically generated:
Cc.SetCreatetime (new date ());
Cc.setBalance (InitialBalance); // Make the balance after you are equal to the initial balance, which is a typical business logic // Save the new credit card to the database, pay attention to the JDO API.
PersistenceManager PM = getPersistenceManager ();
// Detect whether there is a credit card registered with the ID card:
Query Q = PM.NewQuery (CreditCard.class, "IDCARD == _ newidcard");
Q.DeclareParameters ("string _newidcard");
Collection existCards = (Collection) Q.EXECUTE (IDCARD);
IF (existcards.iterator (). Hasnext ()) {
Throw new idcardduplicatedException (); // Already the ID number
}
// The ID number is not repeated, and the credit card object is saved below:
Pm.currentTransAction (). Begin (); // Each time you update the database must be placed in the transaction
PM.makePersistent (CC);
Pm.currentTransAction (). Commit (); // Submit a new object
PM.Close (); // Release JDO resources
Return CC;
}
Public static class idcardduplicateDexception Extends runtimeException {}
Below we run this program, rewrite main.main () as follows:
Public static void main (string [] args) throws exception {
System.out.println ("Start Test Features ...");
InputCard ("Zhang San", "No. 311 Dongfeng East Road", "223003433995431237", "020-38864157", 500.00F, 5000.0F);
System.out.println ("Credit Card has been created!");
}
Compile and run (you can also run "Ant Run" in build.xml), system display:
Start test function ...... jdbc.con.connect jdbc: mysql:? // localhost / test useUnicode = true & characterEncoding = GB2312jdbc.stat.exec set session transaction isolation level read committedjdbc.stat.execQuery select version () jdbc.con.rollbackjdbc. con.closejdbc.con.connect jdbc: mysql: // localhost / test useUnicode = true & characterEncoding = GB2312jdbc.stat.exec set session transaction isolation level read committedjdbc.stat.execUpdate update jdo_keygen set last_used_id = last_used_id where table_name = 'transaction_record?? 'jdbc.stat.execQuery select max (transaction_record_id) from transaction_recordjdbc.stat.exec insert into jdo_keygen (table_name, last_used_id) values (' transaction_record ', 0) jdbc.con.commitjdbc.stat.execUpdate update jdo_keygen set last_used_id = last_used_id ? where table_name = 'credit_card'jdbc.stat.execQuery select max (credit_card_id) from credit_cardjdbc.stat.exec insert into jdo_keygen (table_name, last_used_id) values (' credit_card ', 0) jdbc.con.commitjdbc.con.commitjdbc.con. Rollbackjdo Gen ie: Created RMI registry on port 2388JDO Genie: Bound to jdogenie.jdogenie1pm.createdjdoql.compile credit.system.CreditCardidcard == _ newIdcardjdbc.stat.execQuery select credit_card_id, address, allow_over_draft, balance, create_time, idcard, initial_balance, last_transaction_time, nme, phone, jdo_version from credit_card where idcard = jdbc.con.committx.begintx.commitjdbc.con.connect jdbc:? mysql: // localhost / test useUnicode = true & characterEncoding = GB2312jdbc.stat.exec set session transaction isolation level read committedjdbc.stat? .execupdate update jdo_keygen set last_used_id = last_used_id ? where table_name = '
credit_card'jdbc.stat.execQuery select last_used_id from jdo_keygen where table_name = 'credit_card'jdbc.con.commitjdbc.stat.exec insert into credit_card (credit_card_id, address, allow_over_draft, balance, create_time, idcard, initial_balance, last_transaction_time, nme, phone, JDO_VERSION) VALUES (?,?,?,?,?,?,?,?,?,?) jdbc.con.commitjdbc.con.commitpm.closed credit card has been created! The above information shows that our first function has been completed, and a credit card record has been generated into the database. You can verify it through MySQL database query tool. After we discover the main function, the system did not quit the run, why? It turns out that JDogenie opens the remote control listening service in the default state, which is useful to track the status of WebApp's server status and adjust it. However, here will only interfere with our sight, turn it off: In the JDogenie's workbench, select the "File -> Project Properties" menu, then "Remote Access" check box in the project property configuration dialog box Clear, indicate for remote access, then click "OK" and save the Project.
Then we run Credit.System.main again, this time we see two phenomena: First, the program throws an exception, indicating that the ID number is repeated, which is in line with our expectations; the second is that the system exits, no monitoring Thread, this is the result of changing the configuration just now.
So far, our creation of a credit card is complete, now let's take a look at the JDOQL query functionality integrated with the workbench provided by JDogenie: Select the CreditCard class in the Workbench, then select the menu "Run -> View class extent "You can view all objects of the CreditCard class, here we see the results below:
If we modify the program and create multiple credit cards, you will see the instance objects of more CreditCard classes in this dialog (the above figure has actually displayed two credit card information.
Let's take another function in the demand description, and no longer display the debug tracking information of JDoGenie in the output information (actually shielded this information in the project configuration), as shown (the log level is changed to "ErrorS" ):
4.5.2. Browse credit card information
This feature is just a view of all credit cards. In fact, it has already been seen earlier, which is already easy to complete this feature in the work desk, but we need it in the program here.
We join a method in the main class: listcards ()
/ **
* List all credit card information in the system
* /
Public static void listcards () {
PersistenceManager PM = getPersistenceManager ();
Itextent (CreditCard.class, false) .Itemrator ();
iTr.hasnext ();) {
Object o = itr.next (); system.out.println ("DatastoreIdentity =" JDOHELPER.GETOBJECTID (O) "," O);} PM.Close ();}
This method lists all credit cards in the current system, including automatically generated card numbers (object identity). It can be seen that the content of the method is very simple. You can say it dismissive: Oh, the function of viewing objects in the JDogenie's workbench is alive! Yes, it is true, the reason is very simple: technology people-oriented, JDO's goal is to simplify operation!
Also, change the main () method:
Public static void main (string [] args) throws exception {
System.out.println ("Start Test Features ...");
ListCards ();
}
Then compile, run, and the results are as follows (if you run with Ant, there may be some Ant tool information, no longer explained later):
Start testing function ... DatastoreIdentity = 1979371451-1, credit card: balance = 500.0, cardholder = Zhang San, ID number = 223003433995431237, phone = 020-38864157DataStoreIdentity = 1979371451-11, credit card: balance = 500.0, cardholder = Li Si, ID number = 320012194501032339, phone = 020-38864157
Here, we can see a few: First, the log function of JDogenie has been turned off (the previous settings take effect), and the other is to display the toString () method in CreditCard when the credit card is displayed. As the saying goes, the opportunity is only taken care of the mental head. We seem to have added two data classes to the toString () method, now we see, these two methods have played a role!
4.5.3. Trading credit card
This feature should be considered the basic function of this system, what is the credit card? Just take it. Of course, it is possible to take a certain possibility. I have heard that some people have a wallet, and the n letter is arranged in a row, it is good enough! However, it may not be brushed!
Ok, talk nonsense, we join a new credit card method in the main class Buysomething ():
/ **
* Purchase the credit card function when purchasing a credit card.
* @Param CardID credit card logo, generally can be identified by credit card machine
* @Param Amount transaction amount
* @Param IDCARD The ID number used to verify, can input by the cashier
* @Return's card balance after trading
* @Throws IDCardMismatChexception ID number does not match, refuse to trading
* @Throws toomuchoverdraftException This card has been overducing too much, can't complete this transaction
* /
Public Static Float Buysomething (String CardID, Float Amount, String IDCard)
THROWS IDCARDMISMATCHEXCEPTION, TOOMUCHOVERDRAFTEXCEPTION {PersistenceManager PM = getPersistenceManager ();
PM.currentTransaction (). Begin ();
Creditcard CC = (Creditcard) PM.GetObjectbyid (PM.NewObjectIdInstance (CreditCard.class, CardID), False;
IF (idcard == null ||! idcard.equals (cc.getidcard ()))))
Throw new idcardmismatChexception ();
IF (cc.getbalance () - Amount <-cc.getallowoverdraft ())
Throw new toomuchoverdraftexception ();
TransactionRecord tr = new transactionRecord ();
Tr.SetCard (CC);
Tr.SetAmount (Amount);
Tr.SetCreatetime (new date ());
Tr.SetNote ("One item in Tianshama South University");
PM.makePersistent (TR);
Cc.setbalance (cc.getbalance () - Amount);
Pm.currentTransaction (). commit ();
Float balance = cc.getBalance ();
PM.Close ();
Return balance;
}
Public static class idcardmismatchException extends runtimeException {}
Public static class toomuchoverdraftexception extends runtimeException {}
Then, modify main.main ():
Public static void main (string [] args) throws exception {
System.out.println ("Start Test Features ...");
Float balance = Buysomething ("1979371451-1", 250.0f, "223003433995431237");
System.out.println ("Successful credit card! Balance:" Balance);
}
Run results: Start testing function ... Success! Balance: 250.0
Well, good things, buy one: Start test function ... Success! Balance: 0.0
Ah, there is no money on the card? ! But this is a credit card, I will buy it again! Run: Start the test function ... Success! Balance: -250.0
Haha, it has been overdown, but overdraft is limited to 5000 oceans! I bought it again ... I'm going to stop, let the bank look down, say that I teach users to malicious overdraft, and damage my personal reputation.
4.5.4. Deposit
Deposit, as the name suggests, putting cash into a credit card, which can be credited to buy more items (this also explains ???).
If it has been overdown, the deposit operation in this time can be called "replenishing", haha, stock terminology we borrow.
Method main.Deposit (): / **
* Deposit.
* For deposits, we do not have the maximum amount of money, so this method does not thrown out an exception.
* @Param CardID credit card ID. This is based on persistenceManager.getObjectId ().
* @Param AMOUNT deposit
* @return balance after deposit
* /
Public Static Float Deposit (String CardID, Float Amount) {
// askERT AMOUNT> 0; // The guarantee deposit amount is positive. (It can be said to be nonsense)
PersistenceManager PM = getPersistenceManager ();
PM.currentTransaction (). Begin ();
CreditCard CC = (Creditcard)
PM.GetObjectbyid (PM.NewObjectIdInstance (Creditcard.class, CardID), FALSE
Cc.setBalance (cc.getbalance () Amount);
Pm.currentTransaction (). commit ();
Float balance = cc.getBalance ();
PM.Close ();
Return balance;
}
Main.main () modified:
Public static void main (string [] args) throws exception {
System.out.println ("Start Test Features ...");
Float balance = Deposit ("1979371451-1", 168.0F);
System.out.println ("After the deposit is 168 yuan, the balance is:" balance);
}
Running, the results are as follows: Start testing function ... After depositing 168 yuan, the balance is: -82.0 Why is there 168 yuan? Too much late this month, salary is buckled, two, this figure is more Geely, you can also buy a bowl of noodles with a lot of money: (. (Is it so poor ???)
Finally, after a month, it has sail, and then save the test function ... After the deposit is 168 yuan, the balance is: 86.0
Hey, finally get rid of the shadow of overdraft, the big masters, I finally be very straight to the board!
Hey, the concept of this ancestors is like three mountains, and it is dead! Look at others, there is no good money (overdraft), others live more! He is very honest, just like money is like a forever, the psychological burden is too heavy, can't make a split, the spirit is collapsed ...
4.5.5. Query overdraft report
This feature is to query those credit cards that have been in an overdrawn state in the current system. Here we will use conditions filtering, that is, using JDO query language JDOQL. Add a method ListoverDrafts () in main.
/ **
* Lists the overdraft credit card.
* /
Public static void listoverdrafts () {
PersistenceManager PM = getPersistenceManager ();
Query Q = PM.NewQuery (CreditCard.class, "Balance <0"); // Filter Condition Collection Col = (Collection) Q.Execute ();
ITERATOR ITR = Col.iterator (); itr.hasnext ();) {
System.out.println (ITR.NEXT ());
}
PM.Close ();
}
We note that after a series of operations, no one is overdraft (Zhang San scared a cold sweat, fortunately, I just added the warehouse!). Before performing this method, let's let Zhang San buy something, change the main () method, or call: Buysomething ("1979371451-1", 250.0f, "223003433995431237"); the results are as follows: Start testing function ... Successful card success ... ! Balance: -164.0
Poor Zhang San has made a heavy psychological burden.
Below we have changed main.main (), call to list the overdraft credit card method:
Public static void main (string [] args) throws exception {
System.out.println ("Start Test Features ...");
System.out.println ("The following is a list of credit cards:");
Listoverdrafts ();
}
Run, the results are as follows: Start testing function ... The following is a list of credit cards: credit card: balance = -164.0, cardholder = Zhang San, ID number = 223003433995431237, phone = 020-38864157
Let's whip, continue to advance the next demand.
4.5.6. Query transaction details
This function is relatively complicated, but it is only complicated, and the code is still very simple. We add a method at main ListTransactions ():
/ **
* List the details of a credit card.
* @Param IDCARD ID number
* /
Public Static Void ListTransactions (String IDCARD) {
PersistenceManager PM = getPersistenceManager ();
Query Q = PM.NewQuery (TransactionRecord.class,
"card.idcard == _ p0"); // filter condition
Q.DeclareParameters ("string _P0"); // Declaration Query Parameter Table
Q.SetORDERING ("CreateTime Ascending"); // Listed in time
Collection col = (color) q.execute (idcard); // query by specifying your ID number
ITERATOR ITR = Col.iterator (); itr.hasnext ();) {
System.out.println (ITR.NEXT ());
}
PM.Close ();
}
In this method, we use one of the most attractive features of JDOQL: object reference, "card.idcard == _ p0", which is actually equivalent to two data set table queries, obviously, such statements are more easy to understand , More concise! In addition, we use the query parameter "_P0", and finally use it. In fact, you can also sort in other classes referenced by this class, such as all transaction records in the order of cardholder names, sorting statements will be: Q.SetORDERING ("card.name ascending"); The length of the following table is connected to the lower SQL statement. Finally, we will modify the main.main () method:
Public static void main (string [] args) throws exception {
System.out.println ("Start Test Features ...");
System.out.println ("The following is the transaction record of Zhang San:");
Listtransactions ("223003433995431237");
}
Running, the results are as follows: Start testing function ... The following is Zhang San's transaction record: Transaction record: cardholder = Zhang San, ID number = 223003433995431237, transaction amount = 250.0, time = Mon Jun 30 09:24:51 GMT 2003 transaction record: cardholder = Zhang 3, ID number = 223003433995431237, transaction amount = 250.0, time = Mon Jun 30 09:25:34 GMT 2003 transaction record: cardholder = Zhang San, ID number = 223003433995431237 , Transaction amount = 250.0, time = MON JUN 30 09:27:24 GMT 2003 transaction record: cardholder = Zhang San, ID number = 223003433995431237, transaction amount = 250.0, time = Mon Jun 30 09:29:15 GMT 2003 transaction record: cardholder = Zhang San, ID number = 223003433995431237, transaction amount = 250.0, time = Mon Jun 30 09:29:53 GMT 2003 transaction record: cardholder = Zhang San, ID number = 223003433995431237, Transaction amount = 250.0, time = Mon Jun 30 10:35:57 GMT 2003 These are transaction records generated by our previous call. In fact, the deposit record should also be considered transaction records, but this system has no such need. (Note that more considerations will be considered when you mention the needs, otherwise you will let the developer drill the empty!)
4.6. Let the program more practical
Above we have completed all the needs of the demand, everyone also saw how JDO-based applications developed, which configurations are needed. I will explain again that JDogenie is the most convenient to learn JDO tools, although you have to re-request a trial license every other month.
The words are coming back, the above ways to complete the business logic are too simple, not being developed! (See: The program is written by the supervisor is mad!)
In order to make the program more practical, we need to transform it into a real application, which involves security, performance optimization and index creation, easy operation interface, background operation log, backup, graphic report, and so on. Although these have exceeded the scope of this article, we are still a simple discussion.
There are generally two most common ways to do such systems: a separate GUI program or a browser-based web application. The following recommendations are given below: 4.6.1. Independent program for graphical interface
First, we have to extend a subclass from java.awt.frame, put a few Panels in its window, respectively correspond to several functions in the demand, if this function is required, then in the corresponding panel Put a few TextField, then give a commit button; if this feature does not need to enter a parameter, you can give a function button directly. In the event response of each button, the associated parameters are read from the interface element, in the corresponding method, then the return of the method is received, and the result is printed on the output area of the interface (yes, but also need to be on the interface Add an output area, such as Textarea.
In the business logic method of our Main MAIN, many places are directly printed with the data acquired, and cannot do this in the stand-alone GUI program, only the data acquired by the query (such as a collection) is returned to the called button event. The code processed by the button event is printed to the output area. This is also a way of a MVC, huh, huh.
There is also a suggestion. Because PM.Close (), the object's properties cannot guarantee accurate read, so in a stand-alone GUI program, it is best to keep an open PM, and each method is shared.
4.6.2. WEB applications with JSP
JSP-based web applications are relatively complicated, we need to put jdogenie.jar (incorporate jta.jar and its licrity file) and mysql.jar in the application / web-inf / lib, and then pass your enhance The class code is placed in / web-inf / classes / in the directory structure, and the configuration file Creditsys.jdogenie and System.jdo are placed in the / web-INF / CLASSES / directory.
These are just the configuration of the directory, we also need to transform the previous code.
First, like a stand-alone GUI program, you need to change the business logic method output from System.out.Println () to return the Collection or the specific object of the query to the caller. The caller here is JSP. We can write one to two JSPs for each function. These JSPs only completed the role of data input and display, which is similar to independent programs.
However, since the web application is multi-thread, you need to take into account the problem of concurrent connections, so you cannot only set only one PM that is always open, but a PM request needs to be used each page request. In order to be able to share a PM in different code snippets during processing in a page request, you can refer to this post I published on the JDOCENTRAL forum.
The details of the PM connection pool and resource release have exceeded the scope of this article, please refer to the other article on the 9CBS on JDO (see "Reference article" at the end of this Party).
5. Summary
Below we have summarized the above JDO-based development.
5.1. Changes in development processes
JDO-based processes have been introduced through a picture in this article, mainly adding two steps: writing metadata, and enhancing the class code based on Metadata. These two steps are easy to get through JDogenie's workbench, which are automated.
The rest of the development process is much simpler than the original JDBC package, we no longer have SQL code, no more complex "increase, delete, change, check" universal interface, no longer not supporting the concern, no longer There is ... We only need to operate through the JDO API on a data object model of the object.
Also, we can see that in JDO-based development, various development roles (Javbabean write, JSP writing, database maintenance, configuration) are based on data object models, such as, using JDoGenie to generate data models. After the UML class map, print it down, give each development participant, whether it is written control class JavaBean, or JSP, or database structure maintenance, you can make a baseline based on this graph, not like JDBC-based applications Everyone is developing based on the database structure. JDO has brought us too much, and it needs to be slowly experienced during the development process.
5.2. Will speed? - Performance test data reference
I have used a certain size application to test the performance of JDO. This app has more than ten classes. Each class has 5 ~ 20 attributes, and there is an intricate relationship between classes. It is a complete feature based on Browser's web application. When using the original own JDBC package, there are many processing code related to the database. There are more than 10 K, and after transforming the JDO, these code is gone, in fact, equivalent to these codes to become a JDO vendor support package.
Then the performance test, the original JDBC-based application can process 8 requests per second, and the JDO application with the JDogenie under layer can handle 35 requests per second, using Kodojdo's JDO app (handwritten Java code as JDogenie When you can process 25 requests per second. All of this is attributed to the latency reading mechanism specified in the JDO specification (Lazy Loading Mechanism).
The readers who may have eye will ask: Why do the article starts to say that Kodo is a performance king, but it is not as good as JDogenie? Yes, the eyes are really bright! Such a material, why don't you do private detectives! What kind of X Mei Feng's film is definitely a cannon! Oh, yes, I haven't given an explanation yet. I have said that KODO performance is best, including evaluation of stability. I have been testing the two in the two, using the Javax.jdo.Option.optimisticTictraSction defined by the JDO specification, this way to limit the transaction's lock limit on the application, do not cause pressure to the database, just in the same When the object's concurrent changes, there will be many conflicts. In general, your web application will not visit millions one day? If not, this transaction method can be used. KODO's transaction processing successful opportunity in the test is much larger than JDogenie, the same test time, KODO's similar access count is more than JDogenie, that is, Kodo's successful transaction is more than JDogenie, although the total number of visits is less than JDogenie . In summary, KODO's performance is better than JDogenie. However, JDogenie is also chasing it, I am more optimistic about it!
5.3. Some uncomfortable - the limitations of JDO1.0
Ok, after exciting, it should be a calm reflection.
There is a word, the most worthy of people, only yourself!
I am a fanaticism of JDO. It is unremitting efforts to promote JDO. Of course, I will not be able to pass almost some speech or one-sided, so-called "one leaf barrier, no Taishan". Just like Java followers, it is actually the same. Net has many advantages. Java cannot be compared, such as fast, flexible. I am also calm down, thinking about the shortcomings of JDO1.0 carefully, there are many:
Increase additional steps, configure complex (relative to Direct JDBC) There must be limitations on the data model (there must be a non-refined constructor, attribute access requires getter and setter) two-way object relationship processing is too defect (automatic automatic in the JDO2.0 program) Maintaining object relationships will solve these) JDOQL's API slightly (Declare is a big stack of things than ODMG's OQL standard is not as good as Database statistics (count (), max (), avg (), etc., but already In the JDO2.0 plan)
5.4. JDO2.0 Outlook
Sun's movement is slow, like a late giant. JDO1.0 discussed for four years, only half of the way, JDO2.0 has not officially established, I really don't know what year, you can truly solve all the problems in database applications! However, the participation of the masses is driving, let us put forward our opinions, push JDO2.0 wheel! (We can bombard the email address of the JDO specification, until they say "I will start" or "count, give you 100,000 $, spare me".
6. Reference article (Chinese)
In fact, the articles listed below can basically be found directly on www.9cbs.net to search for the keyword "JDO" technical documentation.
"What is the help of JDO" "JDO can bring us" "JDO resource introduction" "a JDO success case analysis" "JDO experience of a New York Women's Technician" "The most authoritative JDO new book" "Java Data" Objects Chapter 1 Translation "" Select CMP or JDO "
You can also find some other authors written in 9CBS.
7. Reference
JDO Specification Home - JSR12, http://jcp.org/en/jsr/detail? Id = 012 Sun website as J2SE OPTIONAL PACK - http: //java.sun.com/products/jdo/ Core promotion website - http://www.jdocentral.com The most concentrated discussion area - http://www.jdocentral.com/forums/index.php related Chinese resource network - http: // www. 9CBS.NET related Chinese resource network two - http: //www.javaresearch.org Versant's introduction materials: http://www.jdocentral.com/pdf/javadataObjects_mccammon.pdf Composite: http: // www .jdocentral.com / JDO_RESOURCES_BODY.HTML
8. Reference book:
The following information comes from: http://www.jdokecentral.com/jdo_resources_body.html
"Java Data Objects", Author: Robin Roos (UK) "Java Data Objects", Author: Craig Russell (USA) and David Jordan (USA) "Core Java Data Objects", Author: Many people, by the Sun organization "Using and Understanding Java data Objects "author: David Ezzio (USA) some other PDF document: http: copyright //www.javaresearch.org/dn/JDO_introduce.zip article are those of the author himself, but welcome to reprint, provided that indicate the source and original Author. In addition, welcome to some of my articles in my column, and make valuable comments!