4.3 Creating Custom Classes In order to access and modify database objects using a SQLJ program, you must provide a way to translate the information stored in the database objects into a form that the SQLJ program can understand. You do this using the custom Java classes mentioned earlier in this chapter. You can write these custom classes by hand or create them automatically using the JPublisher utility. I recommend using JPublisher to create the custom Java classes, as these classes are rather complicated. When you run JPublisher, it performs the following steps: -
Connects to the database. -
Retrieves the details of the database objects that you specify. -
Generates the custom classes for the specified database objects. The custom classes generated by JPublisher define get accessor and set mutator methods for each of the attributes in the database object; these get and set methods allow you to get an attribute value and set an attribute value, respectively. You can run JPublisher from the command line, or you can use a wizard in JDeveloper. I cover both methods in the following sections. The examples in these sections show you how to generate the custom classes for the t_address and t_customer database object types.  | If you do want to create your own custom classes, you should first study the classes generated by JPublisher to gain an understanding of what is required. |
| 4.3.1 Running JPublisher Using the Command Line JPublisher has a large number of runtime options, of which I use only two in this chapter; for a full description of all the JPublisher options, see Appendix B. To run JPublisher using the command line, you use the jpub command. You can then use the various runtime options to control JPublisher's behavior. When you run JPublisher, you should connect to the schema containing the object types in which you are interested. The following command causes JPublisher to connect to the object_user schema and generate custom classes for the t_address and t_customer database objects: jpub -user=object_user/object_password -sql=t_address,t_customer The options used in this command are as follows: - -user
-
Specifies the database username and password that you want JPublisher to use when it connects to the database. Here, JPublisher connects as the user named object_user, and uses the string "object_password" as the password. - -sql
-
Specifies the object types for which you want JPublisher to generate custom class files. In this example, JPublisher generates custom class files for the t_address and t_customer object types. The -sql option is not mandatory. If you omit it, JPublisher generates custom class files for all object types contained in the schema to which it connects. Once the command shown in the example has completed, JPublisher will have generated the following files: -
t_address.sqlj -
t_addressRef.java -
t_customer.sqlj -
t_customerRef.java  | For Oracle 9i and above, JPublisher generates a .sqlj file only if the relevant object type has methods. |
| These four files are the custom class files, and I will describe their contents later. First, let's talk about the filenames. How does JPublisher come up with the names for these custom class files? If you do not specify the -sql option, the name of the custom class is generated by taking the name of the object type, removing any underscore (_) characters, capitalizing the first character, and capitalizing the first character following an underscore. For example, t_address becomes TAddress. If you do specify the -sql option, then by default the names of the object types specified in the -sql option are used to start the names of their respective custom classes. If you prefer not to use the class names that JPublisher generates, you can use the -sql option to specify your own names for the custom classes. To do this, you place a colon (:) character after the name of the database object type specified in the -sql option, and follow it with the Java name you want to give the custom classes generated for that object. For example: jpub -user=object_user/object_password -sql=t_address:address_type,t_customer:customer_type This command specifies address_type as the name to use when naming custom classes for the t_address object type, and customer_type as the name to use when naming custom classes for the t_customer object type. As a result, JPublisher generates the following four files: -
address_type.sqlj -
address_typeRef.java -
customer_type.sqlj -
customer_typeRef.java If you want to generate custom classes for all object types in your schema, you can do so by omitting the -sql option on the jpub command line. That causes JPublisher to generate custom classes for all the types in the specified schema. In the following command, the -sql option is omitted in order to generate custom classes for all the object types in the object_user schema: jpub -user=object_user/object_password When you omit the -sql option entirely, you give up the ability to specify your own class names. In addition, the names of the files generated by JPublisher for t_address and t_customer are slightly different from those that JPublisher generates automatically when you do use the -sql option. Without the -sql option, JPublisher generates the following file names for the t_address and t_customer object types: -
TAddress.sqlj -
TAddressRef.java -
TCustomer.sqlj -
TCustomerRef.java  | In addition to these files, other custom class files are generated by JPublisher. These custom class files are for the database object types used later in this chapter and in the next chapter. |
| As you can see from the filenames, JPublisher has removed the underscore (_) character and capitalized the initial letters. The code examples later in this chapter use these default class names. 4.3.2 Running JPublisher from JDeveloper In this section, you will see how to generate the TAddress.sqlj and TAddressRef.java custom class files for the t_address database object type using the JPublisher wizard in JDeveloper. If you don't have JDeveloper, don't worry this section is optional. The TAddress.sqlj and TAddressRef.java files generated here are identical to those generated in the previous section using the command-line utility. If you do have JDeveloper and you want to follow along with the examples in this section, use the following two files from this book's web site: Once you have these two files, start JDeveloper and open the sqlj_workspace.jws workspace file. 4.3.2.1 Create a connection Before you can use the JPublisher wizard, you must create a connection to the database using JDeveloper. This connection allows JPublisher to retrieve the details for the database object types. To create a connection using JDeveloper, first select Connections from the Tools menu. This opens the Connection Manager dialog box shown in Figure 4-1. Figure 4-1. The Connection Manager dialog box Click New to begin creating a new connection. The Connection dialog box shown in Figure 4-2 will be displayed. Use the Oracle JDBC Thin driver and set the connection name to OBJECT_USER, the username to object_user, and the password to object_password. The connection name need only be meaningful to you it allows you to distinguish between the various connections you define. The username and password are used when logging in to the database. You can also use the various Oracle JDBC OCI drivers to create a connection, if you wish; see Chapter 3 for details on the Oracle JDBC drivers. Figure 4-2. The Connection dialog box If your database is not on your local machine, ask your DBA what the host ID, SID, and Port fields should be set to in order to access the database. Click Test Connection to ensure the connection to the database can be made. Finally, click OK to create the connection. You will return to the Connection Manager dialog, which now contains the details for the OBJECT_USER connection. This is shown in Figure 4-3. Figure 4-3. The Connection Manager dialog box after defining a connection Click Done. With the connection created, you are ready to run the schema browser. 4.3.2.2 Run the schema browser After creating a connection, you can run the schema browser to select objects of interest. To run the schema browser, click the plus (+) character in the Connections element under the sqlj_workspace.jws file in the far-left panel of the JDeveloper workspace. Then double-click on the OBJECT_USER connection. JDeveloper will open a box with the title OBJECT_USER; this is the schema browser. The schema browser allows you to access the schemas in your database. Your JDeveloper workspace should now appear similar to the one shown in Figure 4-4. Figure 4-4. The JDeveloper workspace with the schema browser open On the left of the schema browser, there is a list of schemas contained in the database. Click the + character to the left of the OBJECT_USER schema, and then click the + to the left of Object Types. This causes the schema browser to display the object types contained in the object_user schema. Double-click on the T_ADDRESS type to display its definition. Your workspace should now be similar to that shown in Figure 4-5. Figure 4-5. The T_ADDRESS object type displayed in the schema browser As you can see, the schema browser now shows the details for the T_ADDRESS object type created earlier in this chapter. When you are ready to generate custom classes, right-click the T_ADDRESS object type name and select Generate Java to start the JPublisher Wizard. 4.3.2.3 Run the JPublisher Wizard The JPublisher Wizard is a dialog that collects information needed to run the JPublisher utility. Instead of passing parameters on a command line, you enter them into the various fields within the dialog. The JPublisher Wizard dialog box is shown in Figure 4-6. Notice the Declaration Name and Use Name fields; the values in these fields determine the names of the custom class files. Figure 4-6. The JPublisher Wizard dialog box with the default declaration and use names As shown in the figure, the default for both of these fields is tAddress: JPublisher has removed the underscore character and used a lowercase initial letter to generate the custom class name. In the JPublisher Wizard dialog box, change the name to TAddress in the Declaration Name and Use Name fields, as shown in Figure 4-7. Figure 4-7. The JPublisher Wizard dialog box with edited fields The Declaration Name is used to generate the TAddress.sqlj file, and the Use Name is used to generate the TAddressRef.java file. Once you have the names correct, go ahead and click OK. The JPublisher Wizard then generates the TAddress.sqlj and TAddressRef.java custom class files. 4.3.3 Understanding the Custom Class Files Now that you have seen how to generate the custom class files for the t_address and t_customer database object types using JPublisher, it's time to learn about their contents. There are two custom class files generated by JPublisher for each database object type that you select: You will use these Java classes later in this chapter to declare host objects in a SQLJ program. These host objects are used to access database objects in a manner similar to the way in which host variables are used to access regular database columns. For each attribute defined in the database object type, there is a corresponding get accessor and set mutator method defined in the Java class. The get methods are used to retrieve attribute values from the host object, while the set methods are used to set those attribute values. Previously, you used JPublisher to generate the following four Java custom class files for the t_address and t_customer object types: - TAddress.sqlj
-
Contains the definition for the TAddress custom class. Use this class to define a host object into which you can select an address object. - TAddressRef.java
-
Contains the definition for the TAddressRef custom class. Use this class to define a host object into which you can place a reference to an address object. - TCustomer.sqlj
-
Contains the definition for the TCustomer custom class. Use this class to define a host object into which you can place a customer object retrieved from either the customers table or the customers2 table. - TCustomerRef.java
-
Contains the definition for the TCustomerRef custom class. Use this class to define a host object into which you can place a reference to a customer object. If you open the TAddress.sqlj file, you will see that it is very cryptic and realize why it is better to have JPublisher create these custom classes for you. For each attribute in the t_address object type, you will see the corresponding get and set methods defined in the TAddress custom class. Because t_address has four attributes named street, city, state, and zip, the TAddress custom class contains the following eight get and set methods: public String getStreet( ) throws SQLException public void setStreet(String street) throws SQLException public String getCity( ) throws SQLException public void setCity(String city) throws SQLException public String getState( ) throws SQLException public void setState(String state) throws SQLException public String getZip( ) throws SQLException public void setZip(String zip) throws SQLException The street, city, and zip attributes in t_address are VARCHAR2 strings, so these methods use Java String types to represent these attributes. The state attribute is a CHAR, and a Java String is also used for this attribute. The TCustomer.sqlj file contains similar methods for accessing the attributes of the t_customer object type. TCustomer.sqlj also contains a Java function named getAge( ), which is used to call the get_age( ) object method defined in the t_customer object type. 4.3.4 Translating and Compiling the Custom Classes Once you have your custom classes, you must translate and compile the .sqlj custom class files using the sqlj utility. You must also compile the .java custom class files using the Java compiler. To translate and compile the TAddress.sqlj and TCustomer.sqlj files, and compile the TAddressRef.java and TCustomerRef.java files using the sqlj utility, use the following command: sqlj TAddress.sqlj TCustomer.sqlj TAddressRef.java TCustomerRef.java In addition to translating the two .sqlj files, this command also runs the Java compiler in order to produce the TAddress.class, TCustomer.class, TAddressRef.class, and TCustomerRef.class files. These files will be used later for accessing the customers table. You could also translate and compile all the .sqlj and .java files using the following command: sqlj *.sqlj *.java If you are using JDeveloper, you don't need to use the command line. Instead, you just add the .sqlj and .java files to your project in the same way you would add any other file: by clicking on the "Add to Workspace or Project" button and selecting the file from the dialog box. Once you've added the files to your project, you compile them from within JDeveloper by selecting each file and using the "Make" function from the Project menu. After compiling your custom classes, you need to give some thought to where you place the .class files that result. If you place the .class files in a directory listed in your CLASSPATH environment variable (described in Chapter 1), then you do not have to do anything extra when you invoke the sqlj utility to translate and compile any SQLJ programs that use those custom classes. sqlj searches the directories listed in the CLASSPATH variable, and the custom class files are included automatically. If your custom class files aren't in a directory listed in your CLASSPATH variable, then you must do one of two things: -
Add the directory containing the .class files to your CLASSPATH variable. -
Use the -classpath command-line option to explicitly include the files when you issue the sqlj command to compile SQLJ programs that use the custom classes. The following command illustrates the use of the -classpath command-line option. Assume that your custom class files are stored in the directory D:\custom_classes, and that you have a program named ObjectExample1.sqlj that makes use of these custom classes (I discuss ObjectExample1.sqlj in detail later in this chapter). The following sqlj command translates and compiles this program. The -classpath option in the command explicitly causes the sqlj utility to include the TAddress.class and TCustomer.class files. sqlj -classpath=D:\custom_classes\TAddress.class; D:\custom_classes\TCustomer.class ObjectExample1.sqlj In my personal experience, I have found that the easiest method for managing custom class files is to keep them in the same directory with my SQLJ programs, and add that directory to my CLASSPATH variable. If you do this, then all you have to do to compile ObjectExample1.sqlj is: sqlj ObjectExample1.sqlj If you are using JDeveloper, you should compile ObjectExample1.sqlj using the "Rebuild ObjectExample1.sqlj" function from the Project menu.  | Using JDeveloper can be tricky when compiling custom classes and programs that use these custom classes. Be very careful to follow these steps exactly. |
| Once you compile ObjectExample1.sqlj using the sqlj utility or JDeveloper, you can run the resultant ObjectExample1 class using the java command or from within JDeveloper. The following example uses the java command to run ObjectExample1: java ObjectExample1 However, you may get the following error: SQLException java.sql.SQLException: unable to convert database class oracle.sql. STRUCT to client class TCustomer This error means that you haven't compiled ObjectExample1.sqlj after compiling the custom class files. Once you have compiled ObjectExample1.sqlj, you should be able to run ObjectExample1 successfully. |