JPA J2SE 桌面應用范例,jpaj2se應用范例
JPA雖然是Java EE規范的一部分,但是可以在J2SE環境下單獨使用,不需要Web相關容器。本篇主要通過Netbeans 自動生成的代碼來學習JPA相關內容。
1.打開Netbeans 8.1 添加Mysql數據庫連接

2.新建Java應用程式,輸入項目名稱JpaExample

3.在項目中右鍵新建其他,選擇主樣例窗體/詳細樣例窗體,輸入類名稱和包名稱

4.選擇第一步建立的數據庫連接->選擇表(user),右側為程式中用到的欄位,默認是全部帶到右邊,不需要的可以移到左邊

5.選擇在Swing界面上顯示的欄位,默認全部在右邊表示全選,不需要的可以移到左邊。點擊完成

6.查看生成的類,persistence.xml是jpa配置文件,User.java是對於table的實體,MasterDetailForm.java是自動生成的Swing界面,自動添加的庫文件包括實現JPA2.1 的EclipseLink和添加連接mysql數據庫的jdbc驅動,都是安裝Netbeans自帶的可以自行替換指定版本。

7.運行,點擊New就可以新增內容,Delete刪除上面Jtable選中的數據,Save保存到數據庫,Refresh 刷新數據,主要是數據庫數據與JPA同步,如果數據庫有變動,刷新後本地JPA顯示變動後數據。

8.代碼分析,完整MasterDetailForm.java如下。

![]()
package com.cc.jpa;
import java.awt.EventQueue;
import java.beans.Beans;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.RollbackException;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* @author dev
*/
public class MasterDetailForm extends JPanel {
public MasterDetailForm() {
initComponents();
if (!Beans.isDesignTime()) {
entityManager.getTransaction().begin();
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
bindingGroup = new org.jdesktop.beansbinding.BindingGroup();
entityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory("ccPU").createEntityManager();
query = java.beans.Beans.isDesignTime() ? null : entityManager.createQuery("SELECT u FROM User u");
list = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : org.jdesktop.observablecollections.ObservableCollections.observableList(query.getResultList());
masterScrollPane = new javax.swing.JScrollPane();
masterTable = new javax.swing.JTable();
idLabel = new javax.swing.JLabel();
usernmaeLabel = new javax.swing.JLabel();
passwordLabel = new javax.swing.JLabel();
nameLabel = new javax.swing.JLabel();
idField = new javax.swing.JTextField();
usernmaeField = new javax.swing.JTextField();
passwordField = new javax.swing.JTextField();
nameField = new javax.swing.JTextField();
saveButton = new javax.swing.JButton();
refreshButton = new javax.swing.JButton();
newButton = new javax.swing.JButton();
deleteButton = new javax.swing.JButton();
FormListener formListener = new FormListener();
org.jdesktop.swingbinding.JTableBinding jTableBinding = org.jdesktop.swingbinding.SwingBindings.createJTableBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, list, masterTable);
org.jdesktop.swingbinding.JTableBinding.ColumnBinding columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${id}"));
columnBinding.setColumnName("Id");
columnBinding.setColumnClass(Integer.class);
columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${usernmae}"));
columnBinding.setColumnName("Usernmae");
columnBinding.setColumnClass(String.class);
columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${password}"));
columnBinding.setColumnName("Password");
columnBinding.setColumnClass(String.class);
columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${name}"));
columnBinding.setColumnName("Name");
columnBinding.setColumnClass(String.class);
bindingGroup.addBinding(jTableBinding);
masterScrollPane.setViewportView(masterTable);
idLabel.setText("Id:");
usernmaeLabel.setText("Usernmae:");
passwordLabel.setText("Password:");
nameLabel.setText("Name:");
org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement.id}"), idField, org.jdesktop.beansbinding.BeanProperty.create("text"));
binding.setSourceUnreadableValue("null");
bindingGroup.addBinding(binding);
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement != null}"), idField, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement.usernmae}"), usernmaeField, org.jdesktop.beansbinding.BeanProperty.create("text"));
binding.setSourceUnreadableValue("null");
bindingGroup.addBinding(binding);
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement != null}"), usernmaeField, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement.password}"), passwordField, org.jdesktop.beansbinding.BeanProperty.create("text"));
binding.setSourceUnreadableValue("null");
bindingGroup.addBinding(binding);
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement != null}"), passwordField, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement.name}"), nameField, org.jdesktop.beansbinding.BeanProperty.create("text"));
binding.setSourceUnreadableValue("null");
bindingGroup.addBinding(binding);
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement != null}"), nameField, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
saveButton.setText("Save");
saveButton.addActionListener(formListener);
refreshButton.setText("Refresh");
refreshButton.addActionListener(formListener);
newButton.setText("New");
newButton.addActionListener(formListener);
deleteButton.setText("Delete");
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, masterTable, org.jdesktop.beansbinding.ELProperty.create("${selectedElement != null}"), deleteButton, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
deleteButton.addActionListener(formListener);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(newButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(refreshButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(saveButton)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(idLabel)
.addComponent(usernmaeLabel)
.addComponent(passwordLabel)
.addComponent(nameLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(idField, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE)
.addComponent(usernmaeField, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE)
.addComponent(passwordField, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE)
.addComponent(nameField, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE))
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(masterScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteButton, newButton, refreshButton, saveButton});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(masterScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 130, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(idLabel)
.addComponent(idField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(usernmaeLabel)
.addComponent(usernmaeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(passwordLabel)
.addComponent(passwordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(nameLabel)
.addComponent(nameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(saveButton)
.addComponent(refreshButton)
.addComponent(deleteButton)
.addComponent(newButton))
.addContainerGap())
);
bindingGroup.bind();
}
// Code for dispatching events from components to event handlers.
private class FormListener implements java.awt.event.ActionListener {
FormListener() {}
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (evt.getSource() == saveButton) {
MasterDetailForm.this.saveButtonActionPerformed(evt);
}
else if (evt.getSource() == refreshButton) {
MasterDetailForm.this.refreshButtonActionPerformed(evt);
}
else if (evt.getSource() == newButton) {
MasterDetailForm.this.newButtonActionPerformed(evt);
}
else if (evt.getSource() == deleteButton) {
MasterDetailForm.this.deleteButtonActionPerformed(evt);
}
}
}// </editor-fold>
@SuppressWarnings("unchecked")
private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {
entityManager.getTransaction().rollback();
entityManager.getTransaction().begin();
java.util.Collection data = query.getResultList();
for (Object entity : data) {
entityManager.refresh(entity);
}
list.clear();
list.addAll(data);
}
private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {
int[] selected = masterTable.getSelectedRows();
List<com.cc.jpa.User> toRemove = new ArrayList<com.cc.jpa.User>(selected.length);
for (int idx = 0; idx < selected.length; idx++) {
com.cc.jpa.User u = list.get(masterTable.convertRowIndexToModel(selected[idx]));
toRemove.add(u);
entityManager.remove(u);
}
list.removeAll(toRemove);
}
private void newButtonActionPerformed(java.awt.event.ActionEvent evt) {
com.cc.jpa.User u = new com.cc.jpa.User();
entityManager.persist(u);
list.add(u);
int row = list.size() - 1;
masterTable.setRowSelectionInterval(row, row);
masterTable.scrollRectToVisible(masterTable.getCellRect(row, 0, true));
}
private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {
try {
entityManager.getTransaction().commit();
entityManager.getTransaction().begin();
} catch (RollbackException rex) {
rex.printStackTrace();
entityManager.getTransaction().begin();
List<com.cc.jpa.User> merged = new ArrayList<com.cc.jpa.User>(list.size());
for (com.cc.jpa.User u : list) {
merged.add(entityManager.merge(u));
}
list.clear();
list.addAll(merged);
}
}
// Variables declaration - do not modify
private javax.swing.JButton deleteButton;
private javax.persistence.EntityManager entityManager;
private javax.swing.JTextField idField;
private javax.swing.JLabel idLabel;
private java.util.List<com.cc.jpa.User> list;
private javax.swing.JScrollPane masterScrollPane;
private javax.swing.JTable masterTable;
private javax.swing.JTextField nameField;
private javax.swing.JLabel nameLabel;
private javax.swing.JButton newButton;
private javax.swing.JTextField passwordField;
private javax.swing.JLabel passwordLabel;
private javax.persistence.Query query;
private javax.swing.JButton refreshButton;
private javax.swing.JButton saveButton;
private javax.swing.JTextField usernmaeField;
private javax.swing.JLabel usernmaeLabel;
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration
public static void main(String[] args) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MasterDetailForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MasterDetailForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MasterDetailForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MasterDetailForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setContentPane(new MasterDetailForm());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
View Code
主要部分:
entityManager初始化,ccPU是在persistence.xml中定義的persistence-unit 的名稱, query 和list的 代碼 一個是新建一個查詢,另一個是查出所有資料。query其實可以用另一種寫法,使用entityManager.createNamedQuery("User.findAll");
查看User.java文件會發現,Netbeans 生成的文件裡面默認生成了幾個Query,也可以根據需要自行添加,集中管理。
entityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory("ccPU").createEntityManager();
query = java.beans.Beans.isDesignTime() ? null : entityManager.createQuery("SELECT u FROM User u");
list = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : org.jdesktop.observablecollections.ObservableCollections.observableList(query.getResultList());
User:

![]()
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.cc.jpa;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
*
* @author dev
*/
@Entity
@Table(name = "user", catalog = "cc", schema = "")
@NamedQueries({
@NamedQuery(name = "User.findAll", query = "SELECT u FROM User u"),
@NamedQuery(name = "User.findById", query = "SELECT u FROM User u WHERE u.id = :id"),
@NamedQuery(name = "User.findByUsernmae", query = "SELECT u FROM User u WHERE u.usernmae = :usernmae"),
@NamedQuery(name = "User.findByPassword", query = "SELECT u FROM User u WHERE u.password = :password"),
@NamedQuery(name = "User.findByName", query = "SELECT u FROM User u WHERE u.name = :name")})
public class User implements Serializable {
@Transient
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@Column(name = "usernmae")
private String usernmae;
@Basic(optional = false)
@Column(name = "password")
private String password;
@Basic(optional = false)
@Column(name = "name")
private String name;
public User() {
}
public User(Integer id) {
this.id = id;
}
public User(Integer id, String usernmae, String password, String name) {
this.id = id;
this.usernmae = usernmae;
this.password = password;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
Integer oldId = this.id;
this.id = id;
changeSupport.firePropertyChange("id", oldId, id);
}
public String getUsernmae() {
return usernmae;
}
public void setUsernmae(String usernmae) {
String oldUsernmae = this.usernmae;
this.usernmae = usernmae;
changeSupport.firePropertyChange("usernmae", oldUsernmae, usernmae);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
String oldPassword = this.password;
this.password = password;
changeSupport.firePropertyChange("password", oldPassword, password);
}
public String getName() {
return name;
}
public void setName(String name) {
String oldName = this.name;
this.name = name;
changeSupport.firePropertyChange("name", oldName, name);
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.cc.jpa.User[ id=" + id + " ]";
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
changeSupport.removePropertyChangeListener(listener);
}
}
View Code
New,主要是新增一個新的User對象,沒有寫到數據庫中,主要是前端操作
com.cc.jpa.User u = new com.cc.jpa.User();
entityManager.persist(u);
list.add(u);
int row = list.size() - 1;
masterTable.setRowSelectionInterval(row, row);
masterTable.scrollRectToVisible(masterTable.getCellRect(row, 0, true));
Delete,執行entityManager.remove(u)並沒有寫到數據庫是因為有開啟Transaction ,在保存的時候才會commit
int[] selected = masterTable.getSelectedRows();
List<com.cc.jpa.User> toRemove = new ArrayList<com.cc.jpa.User>(selected.length);
for (int idx = 0; idx < selected.length; idx++) {
com.cc.jpa.User u = list.get(masterTable.convertRowIndexToModel(selected[idx]));
toRemove.add(u);
entityManager.remove(u);
}
list.removeAll(toRemove);
Save,主要就是Transaction 的提交以及異常處理
try {
entityManager.getTransaction().commit();
entityManager.getTransaction().begin();
} catch (RollbackException rex) {
rex.printStackTrace();
entityManager.getTransaction().begin();
List<com.cc.jpa.User> merged = new ArrayList<com.cc.jpa.User>(list.size());
for (com.cc.jpa.User u : list) {
merged.add(entityManager.merge(u));
}
list.clear();
list.addAll(merged);
}
Refresh,同步數據庫數據
entityManager.getTransaction().rollback();
entityManager.getTransaction().begin();
java.util.Collection data = query.getResultList();
for (Object entity : data) {
entityManager.refresh(entity);
}
list.clear();
list.addAll(data);
此范例主要是J2SE 下JPA的使用,實際項目中,可能設計很多table,程式也會相應的分層,如果只是學習一下JPA的特性熟悉下方法,這種方式也是沒問題的。使用eclipse 創建JPA時 EclipseLink 需要單獨下載,EclipseLink 前身是Oracle TopLink ,以前商業框架 ADF的一部分,用JPA 選擇EclipseLink ,Hibernate 或其他實現都沒有關系,而且只用JPA的功能,不用實現提供的一些擴展的話,切換使用都是沒有問題的,就像JSP頁面用不同的容器,Tomcat、Jetty、GlassFish結果是沒差別的。