In this tutorial, you use the NetBeans IDE to generate and deploy a web application that displays data from a database. In the tutorial you generate a web application with CRUD (Create, Read, Update, Delete) functionality that uses the Java Persistence API (JPA) to manage the database transaction. In the tutorial you first create entity classes based on tables in a database and then create JavaServer Faces (JSF) pages from the entity classes using the JSF Pages from Entity Classes wizard.
The JSF Pages from Entity Classes wizard enables you to quickly and easily generate JSF pages for working with a database based on the entity classes in your project. The wizard was updated in NetBeans IDE 6.1 to add new features, support more cases and to generate more robust code. The improvements to the wizard include the following:
The generated code also includes checks to verify that the current entity is correct in order to prevent errors if a user deviates from the normal page flow. Errors may occur, for example, when working in multiple browser tabs.
Using the code generated by the wizard, it is now easier to remove fields from the generated JSPs. It is also now much easier to apply styles to the generated pages.
Note: This document uses the NetBeans IDE 6.1 Release. If you are using NetBeans IDE 6.5, see Generating a JavaServer Faces CRUD Application from a Database in NetBeans IDE 6.5.
Contents
To follow this tutorial, you need the following software and resources.
This tutorial uses a consulting agency database called consult. The database is not included when you install the IDE so you need to first create the database to follow this tutorial.
The consult database was designed to demonstrate the scope of IDE support for handling a variety of database structures. The database is thus not intended as an example of recommended database design. Instead, it attempts to incorporate many of the relevant features that are potentially found in a database design. For example, the consult database contains all possible relationship types, composite primary keys, and many different data types. See the tables for a more detailed overview of the database structure.
A new node appears under the Databases node (jdbc:derby://localhost:1527/consult [consult on CONSULT]).
Right-click the new node and choose Connect. Expand the consult database node, right-click the Tables node, and choose Execute Command to open the SQL editor. Copy and paste the contents of the create-consult.sql file into the SQL editor.
When you click Run SQL, the following output appears in the Output window.
To see the if the tables were created correctly, right-click the Tables node in the Services window and choose Refresh. You should see the database tables under the Tables node. You can expand a table node to see the table columns, indexes and any foreign keys. You can right-click a column and choose Properties to view additional information about the column.
If you look at the structure of the consult database you can see that the database contains tables that have a variety of relationships and various field types. When creating entity classes from a database, the IDE automatically generates the appropriate code for the various field types. The following table describes the tables found in the consult database.
The consult database includes a variety of relationships. When creating entity classes from a database, the IDE automatically generates the appropriate code for the table relationships, adding the appropriate annotations to the fields in the entity classes. The following table describes the table relationships found in the consult database. (The inverse relationships are not shown.)
Now that the database is created, you can create the web application and use the Entity Classes from Database wizard to generate entity classes based on the database tables.
In this exercise you create a web project and add the JavaServer Faces framework to the project. When you create the project, you will select JavaServer Faces in the Frameworks panel of the New Project wizard.
Note: When selecting the framework, be sure to select the JavaServer Faces framework, NOT Visual Web JavaServer Faces.
When you click Finish, the IDE creates the web application project and opens WelcomeJSF.jsp in the editor. You can close WelcomeJSF.jsp because you will not need to edit this file.
After you create the database and the database connection is registered with the IDE, you can use the Entity Classes from Database wizard to quickly generate entity classes based on the tables in the database. The IDE can generate entity classes for each table that you select, and can also generate any necessary entity classes for related tables.
The tables in the consult database appear in the Available Tables listbox.
Click Add All in the wizard. Click Next.
Type entities as the Package. Make sure that the checkbox to generate named queries is selected. Click Create Persistence Unit to open the Create Persistence Unit dialog box. Click Create in the dialog box to create the persistence unit and return to the wizard.
You can keep the default values for the persistence unit.
Click Finish.When using the wizard to create entity classes from a database, the IDE examines the relationships between the tables. In the Projects window, if you expand the entities Source Package node you can see that the IDE generated an entity class for each table except for the PROJECT_CONSULTANT table. The IDE did not create an entity class for PROJECT_CONSULTANT because the table is a join table.
The IDE also generated two additional classes for the tables with composite primary keys: CLIENT and PROJECT. The primary key classes for these tables (ClientPK.java and ProjectPK.java) have PK appended to the name.
Now that the entity classes are generated, you need to make small changes to the entity classes to add code not generated by the wizard. By adding the code before you create the JSF pages from the classes, you take advantage of the improved code generation functionality in the wizard.
When creating the entity classes, the Entity Classes from Database wizard does not add @GeneratedValue annotations or optional annotation elements to the entity classes. By adding the optional annotation elements, the JSF Pages from Entity Classes wizard can generate code that includes checks to prevent non-nullable column violations.
In this exercise you make the following changes to the default code generated by the Entity Classes from Database wizard.
If you look at the SQL script you used to create the database, you can see that for some of the primary key columns in the tables the GENERATED ALWAYS AS IDENTITY keywords are used to indicate that the columns are autogenerated.
Apply the annotation element (optional = false) on all non-nullable many-to-one (@ManyToOne) and one-to-one (@OneToOne) relationshipsAdding this element will cause the IDE to generate required checks when you create the JSF pages using the JSF Pages from Entity Classes wizard. By generating required checks, you prevent the user from attempting to use a null value in a non-nullable database column.
Customize the implementations of the toString method in the entity classesIn the Client and Recruiter classes you will also modify the annotations to change the relationship between clients and recruiters from one-to-many to one-to-one. Because a nullable one-to-many relationship already exists between recruiters and consultants, for demonstration purposes in this tutorial you will establish a nullable one-to-one relationship between clients and recruiters.
Open the Address entity class and make the following changes.
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ADDRESS_ID", nullable = false)
private Integer addressId;
You can use the IDE's code completion to help you add annotations and annotation elements. When you use code completion, the IDE automatically adds the appropriate import statement for you.
Modify the return statement of the toString method to return the full address:
return line1 + ", " + line2 + ", " + city + ", " + region + ", " + country + ", " + postalCode;
You can use the IDE's code completion to help you add the fields.
Fix your imports, if necessary, and save your changes.Open the Billable entity class and make the following changes.
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "BILLABLE_ID", nullable = false)
private Long billableId;
Modify the @ManyToOne annotation on the consultantId and project fields to add the (optional = false) element.
@JoinColumn(name = "CONSULTANT_ID", referencedColumnName = "CONSULTANT_ID")
@ManyToOne(optional = false)
private Consultant consultantId;
@JoinColumns({@JoinColumn(name = "CLIENT_NAME", referencedColumnName = "CLIENT_NAME"), @JoinColumn(name = "CLIENT_DEPARTMENT_NUMBER", referencedColumnName = "CLIENT_DEPARTMENT_NUMBER"), @JoinColumn(name = "PROJECT_NAME", referencedColumnName = "PROJECT_NAME")})
@ManyToOne(optional = false)
private Project project;
Modify the return statement of the toString method to return the description, consultant id and project:
public String toString() {
return description + ", " + consultantId + ", " + project;
Fix your imports, if necessary, and save your changes.
@OneToOne(mappedBy = "client")
private Recruiter recruiter;
Modify the getters and setters for Collection<Recruiter> recruiterCollection according to the changes in the name of the field. The new getter and setter will look like the following:
public Recruiter getRecruiter() {
return recruiter;
}
public void setRecruiter(Recruiter recruiter) {
this.recruiter = recruiter;
}
It may be simpler to delete the getter and setter for Collection<Recruiter> recruiterCollection and then generate a new getter and setter for Recruiter recruiter using the Insert Code dialog. To create a new getter and setter, right-click in the source code and choose Insert Code (Alt-Insert) and then select Getter and Setter. Select recruiter in the Generate Getter and Setter dialog box and click Generate.
Modify the @OneToOne annotation on the billingAddress field to add the (optional = false) property.
@JoinColumn(name = "BILLING_ADDRESS", referencedColumnName = "ADDRESS_ID")
@OneToOne(optional=false)
private Address billingAddress;
Modify the return statement of the toString method to return String.valueOf(clientPK):
public String toString() {
return String.valueOf(clientPK);
}
Fix your imports, if necessary, and save your changes.
public String toString() {
return clientName + ", " + "Dept. " + clientDepartmentNumber;
}
Save your changes.
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CONSULTANT_ID", nullable = false)
private Integer consultantId;
Modify the @ManyToOne annotation on the statusId field to add the (optional = false) property.
@JoinColumn(name = "STATUS_ID", referencedColumnName = "STATUS_ID")
@ManyToOne(optional=false)
private ConsultantStatus statusId;
Modify the return statement of the toString method to return the email:
public String toString() {
return email;
}
Fix your imports, if necessary, and save your changes.
public String toString() {
return statusId + ", " + description;
}
Save your changes.
@JoinColumns({@JoinColumn(name = "CLIENT_NAME", referencedColumnName = "CLIENT_NAME", insertable = false, updatable = false), @JoinColumn(name = "CLIENT_DEPARTMENT_NUMBER", referencedColumnName = "CLIENT_DEPARTMENT_NUMBER", insertable = false, updatable = false)})
@ManyToOne(optional=false)
private Client client;
Modify the return statement of the toString method to return the following:
public String toString() {
return (projectPK == null ? "(unnamed project)" : projectPK.getProjectName()) + ", " + client;
}
Save your changes.
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "RECRUITER_ID", nullable = false)
private Integer recruiterId;
Modify the @ManyToOne annotation on the client field to mark the relationship as one-to-one.
@OneToOne
private Client client;
Modify the return statement of the toString method to return the email:
public String toString() {
return email;;
}
Fix your imports, if necessary, and save your changes.Now that the classes are created, you can create a web application for displaying and modifying the data. You will use the JSF Pages from Entity Classes wizard to generate a JavaServer Faces application from the entity classes. For each entity class the wizard will generate the following:
The JSF Pages from Entity Classes wizard will generate code that includes checks based on the modifications you made to the entity classes.
The Available Tables pane of the wizard lists the seven entity classes in the project. The wizard does not list the embeddable classes (ClientPK.java and ProjectPK.java)
Click Add All to move all the classes to the Selected Entity Classes pane of the wizard. Click Next.
Type beans for the Package. Click Finish.When you click Finish, the IDE creates the converter and controller classes for each entity class in the beans package. Each controller class handles the operations for the corresponding entity class, including creating, editing, and destroying instances of the entity class via the Java Persistence API. Each converter class implements the javax.faces.convert.Converter interface defined by JavaServer Faces and performs the work of converting instances of the corresponding entity class to String objects and vice versa.
If you expand the Web Pages node, you can see that the IDE generated a folder for each of the entity classes. Each folder contains the files Detail.jsp, Edit.jsp, List.jsp and New.jsp. The IDE also modified welcomeJSF.jsp to insert links to each of the List.jsp pages.
If you expand the Configuration Files node and open faces-config.xml in the XML editor, you can see that the IDE inserted the managed-bean and converter elements for each of the controller and converter classes. The IDE also inserted a navigation-rule element for each JSP, indicating the logical outcome that causes the application to navigate to that JSP.
Now that you have finished creating the application, you can deploy and run the application.
The IDE saves all changed files, rebuilds the application, and deploys the application to the server. Your default web browser opens to the local address http://localhost:8080/ConsultingAgency/.
Click the links to view and add details.
When you start clicking the links and adding data, you can see how the relationships between the tables function.
For more information about using NetBeans IDE to develop web applications using Java Persistence and JSF, see the following resources:
You are viewing a mobilized version of this site...
View original page here