Java持久化數據的方式——JDBC&ORM&JPA
JDBC
什麼是JDBC?
有了JDBC之後的好處
JDBC完成用戶的CURD
jdbc.properties:配置連接數據庫的四大基本參數。
className=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root
User實體類
import lombok.Data;
@Data
public class User {
private Integer uid;
private String uname;
private String pwd;
private Integer sex;
private Integer age;
}
sql建表語句
CREATE TABLE `users` (
`uid` int(10) NOT NULL AUTO_INCREMENT COMMENT '用戶id',
`uname` varchar(255) DEFAULT NULL COMMENT '用戶姓名',
`pwd` varchar(255) DEFAULT NULL COMMENT '用戶密碼',
`sex` int(1) DEFAULT NULL COMMENT '用戶性別,1:男,0:女',
`age` int(3) DEFAULT NULL COMMENT '用戶年齡',
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
CURD代碼
package cn.xxxq.jdbc.statement;
import cn.xxxq.jdbc.domain.User;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 使用Statement對象執行增刪改查SQL語句,有SQL注入的風險。
*/
public class JDBC_CURD_Statement {
private static String className;
private static String url;
private static String username;
private static String password;
/*
使用靜態代碼塊在類加載的時候讀取外部屬性文件
*/
static {
InputStream in = JDBC_CURD_Statement.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
try {
properties.load(in);
className = properties.getProperty("className");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
selectAllUser();
// insert();
// update();
// delete();
}
/**
* 查詢所有用戶
*/
public static void selectAllUser(){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//註冊驅動
Class.forName(className);
//獲取連接對象
connection = DriverManager.getConnection(url, username, password);
//獲取SQL執行對象
statement = connection.createStatement();
/*執行SQL語句*/
String sql = "select * from users";
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
int uid = resultSet.getInt("uid");
int sex = resultSet.getInt("sex");
int age = resultSet.getInt("age");
String uname = resultSet.getString("uname");
String pwd = resultSet.getString("pwd");
User user = new User();
user.setUid(uid);
user.setUname(uname);
user.setPwd(pwd);
user.setSex(sex);
user.setAge(age);
System.out.println(user);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (resultSet!=null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement!=null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
/**
* 刪除用戶
*/
public static void delete(){
Connection connection = null;
Statement statement = null;
try {
Class.forName(className);
connection = DriverManager.getConnection(url, username, password);
statement = connection.createStatement();
String sql = "delete from users where uid = 7";
int i = statement.executeUpdate(sql);
System.out.println(i==1?"刪除成功!":"刪除失敗!");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement!=null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* 修改用戶
*/
public static void update(){
Connection connection = null;
Statement statement = null;
try {
Class.forName(className);
connection = DriverManager.getConnection(url, username, password);
statement = connection.createStatement();
String sql = "update users set uname = '小二',age=28 where uid = 7";
int i = statement.executeUpdate(sql);
System.out.println(i==1?"修改成功!":"修改失敗!");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement!=null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* 保存用戶
*/
public static void insert(){
Connection connection = null;
Statement statement = null;
try {
Class.forName(className);
connection = DriverManager.getConnection(url, username, password);
statement = connection.createStatement();
String sql = "insert into users values(default,'老九','lj','1','39')";
int i = statement.executeUpdate(sql);
System.out.println(i==1?"保存成功!":"保存失敗!");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement!=null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
}
ORM
什麼是ORM?
對象關係映射(Object Relational Mapping,簡稱ORM),是建立實體類和數據庫表之間的關係,
從而達到操作實體類就相當於操作數據庫表的目的。
ORM思想
操作實體類就是操作數據庫表
建立兩個映射關係:
實體類與數據庫表的映射
實體類屬性與數據庫表字段的映射
實現ORM思想的框架:
Hibernate,MyBatis(半ORM思想)
JPA規範
Java持久化API(Java Persistence API)。就是將數據持久化(保存在數據庫中)的一套規範。
使用JPA規範完成數據庫的操作,底層需要Hibernate作爲其實現類來完成數據持久化工作。
JPA完成客戶的CURD
創建Maven工程導入依賴
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<!--junit單元測試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!--測試環境有效-->
<scope>test</scope>
</dependency>
<!--hibernate對JPA規範的實現包-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.0.7.Final</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.0.7.Final</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
sql建表語句
CREATE TABLE `cst_customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',
`cust_name` varchar(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
`cust_source` varchar(32) DEFAULT NULL COMMENT '客戶信息來源',
`cust_industry` varchar(32) DEFAULT NULL COMMENT '客戶所屬行業',
`cust_level` varchar(32) DEFAULT NULL COMMENT '客戶級別',
`cust_address` varchar(128) DEFAULT NULL COMMENT '客戶聯繫地址',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '客戶聯繫電話',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Customer實體類
常用註解說明:
@Data:Lombok插件中的註解,自動生成getter、setter、toString等方法。
@Entity:聲明當前類是實體類。
@Table:配置實體類與數據庫表的映射關係。
name(@Table註解的參數):
:配置數據庫表名稱。
@Id:聲明該字段是主鍵。
@GeneratedValue:指定主鍵的生成方式。
strategy(@GeneratedValue註解的參數):
GennerationType.IDENTITY:主鍵自增。
@Column:配置實體類屬性和表字段的映射關係。
name(@Column註解的參數):
表字段名稱。
@Data
@Entity
@Table(name = "cst_customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)//主鍵自增
@Column(name = "cust_id")
private Long custId; //客戶的主鍵
@Column(name = "cust_name")
private String custName;//客戶名稱
@Column(name = "cust_source")
private String custSource;//客戶來源
@Column(name = "cust_level")
private String custLevel;//客戶級別
@Column(name = "cust_industry")
private String custIndustry;//客戶所屬行業
@Column(name = "cust_phone")
private String custPhone;//客戶的聯繫方式
@Column(name = "cust_address")
private String custAddress;//客戶地址
}
JPA的核心配置文件
配置persistent-unit節點:持久化單元
name:持久化單元名稱。
transaction-type:事務類型。
RESOURCE_LOCAL:本地事務管理(多個表存在一個數據庫中)
JTA:分佈式事務管理(不同的表分散在不同數據庫)
<persistence-unit name="myJPA" transaction-type="RESOURCE_LOCAL"></persistence-unit>
jpa的實現方式: Hibernate
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
數據庫連接參數
<properties>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
</properties>
Hibernate額外的配置(可選)
hibernate.show.sql: 是否顯示sql,false(不顯示),true(顯示)
hibernate.hbm2ddl.auto: 是否創建數據庫表
create:程序運行時創建數據庫表(如果有表,先刪除表再創建)
update:程序運行時不會創建表(如果有表,不會創建表)
none:不會創建表
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
完整的核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="myJPA" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
CURD代碼
public class CURD_Test {
/**
* 保存客戶
*/
@Test
public void save(){
//1.加載配置文件創建工廠對象(實體管理器工廠)
EntityManagerFactory myJPA = Persistence.createEntityManagerFactory("myJPA");
//2.通過實體管理器工廠獲取實體管理器
EntityManager entityManager = myJPA.createEntityManager();
//3.獲取事務對象並開啓事務
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//4.保存操作
Customer customer = new Customer();
customer.setCustName("張三");
customer.setCustAddress("廣東省廣州市");
entityManager.persist(customer);
//5.提交事務
transaction.commit();
//6.關閉資源
entityManager.close();
myJPA.close();
}
}
JPA API
Persistence
Persistence對象主要作用是用於獲取EntityManagerFactory對象的。
通過調用該類的createEntityManagerFactory靜態方法,根據配置文件中持久化單元名稱創建EntityManagerFactory。
EntityManagerFactory
EntityManagerFactory接口主要用來創建EntityManager對象。
EntityManagerFactory是一個線程安全的對象。多個線程訪問同一個EntityManagerFactory對象不會有線程安全問題。
EntityManager
EntityManager是完成持久化操作的核心對象。
實體類作爲普通java對象,只有在調用 EntityManager將其持久化後纔會變成持久化對象。
通過調用EntityManager的方法完成獲取事務,以及持久化數據庫的操作。
getTransaction : 獲取事務對象
persist : 保存操作
merge : 更新操作
remove : 刪除操作
find/getReference : 根據id查詢
EntityTransaction
EntityTransaction是完成事務操作的核心對象。
begin:開啓事務
commit:提交事務
rollback:回滾事務