整合hibernate與JPA
JPA(Java Persistence)是SUN公司推出的一套基于ORM的規範,hibernate架構中提供了JPA的實作。 Hibernate中有自己獨立的ORM操作資料庫方式,也有JPA規範實作的操作資料庫方式。 JPA的特點: (1)、 JPA 架構中支援大資料集、事務、 并發等容器級事務,這使得 JPA 超越了簡單持久化架構的局限,在企業應用發揮更大的作用。 (2)、 在 JPA 架構下建立實體和建立Java 類一樣簡單,沒有任何的限制和限制,隻需要使用 javax.persistence.Entity 進行注釋,JPA 的架構和接口也都非常簡單,沒有太多特别的規則和設計模式的要求,開發者可以很容易的掌握。JPA 基于非侵入式原則設計,是以可以很容易的和其它架構或者容器內建。 (3)、 JPA 的查詢語言是面向對象而 非面向資料庫的,它以面向對象的自然文法構造查詢語句,可以看成是 Hibernate HQL 的等價物。JPA 定義了獨特的JPQL ( Java Persistence Query Language ),JPQL 是EJB QL 的一種擴充,它是針對實體的一種查詢語言,操作對象是實體,而不是關系資料庫的表,而且能夠支援批量更新和修改、JOIN 、GROUP BY 、HAVING 等通常隻有 SQL 才能夠提供的進階查詢特性,甚至還能夠支援子查詢。
下面我将通過一個多對多的例子來整合Hibernate與JPA(多個使用者對應多個角色) (1)、建立一個動态的web項目 拷貝Hibernate的全部jar包到工程中。如下圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyN3ETNyEzM3EzMwETM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
(2)、建立user表、role表與中間表user_role 并寫javabean檔案并加上注解 User.java
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
/**
* 多對多的配置
* @author 帥哥
*
*/
@Entity //指明目前是個實體類
@Table(name="user") //對應資料庫中的表名
public class User implements Serializable{
@Id //主鍵
@Column(name="uid") //對應資料庫的表中的字段名
@GenericGenerator(name="mynative",strategy="native") //這個是hibernate中提供的外鍵生成政策。
@GeneratedValue(generator="mynative")//generator中引入上面的name值
private Integer uid;
@Column(name="cname") //對應資料庫的表中的字段名,名稱相同時,也可以省略
private String uname;
//user沒有放棄外鍵維護,是以需要配置中間表
@ManyToMany(targetEntity=Role.class,cascade={CascadeType.PERSIST})
//name中間表的名字,joinColumns和使用者表做主外鍵關聯
//inverseJoinColumn 和角色表做主外鍵關聯
@JoinTable(name="user_role",joinColumns={@JoinColumn(name="uid",referencedColumnName="uid")},
inverseJoinColumns={@JoinColumn(name="rid",referencedColumnName="rid")})
private Set<Role> roles=new HashSet<>();
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role.java
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Entity //指明目前是個實體類
@Table(name="role") //對應資料庫中的表名
public class Role implements Serializable{
@Id //主鍵
@Column(name="rid") //對應資料庫的表中的字段名
@GenericGenerator(name="mynative",strategy="native") //這個是hibernate中提供的外鍵生成政策。
@GeneratedValue(generator="mynative")//generator中引入上面的name值
private Integer rid;
@Column(name="rname") //對應資料庫的表中的字段名,名稱相同時,也可以省略
private String rname;
//role放棄外鍵維護
@ManyToMany(targetEntity=User.class,mappedBy="roles")
private Set<User> users=new HashSet<>();
public Integer getRid() {
return rid;
}
public void setRid(Integer rid) {
this.rid = rid;
}
public String getRname() {
return rname;
}
public void setRname(String rname) {
this.rname = rname;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
(3)、在src下建立一個目錄為META-INF,裡面放入核心配置檔案名為persistence.xml這兩個名字是固定的,不能換名字。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<!--Name屬性用于定義持久化單元的名字 (name必選,空值也合法); transaction-type 指定事務類型(可選) 取值: JTA:預設值
RESOURCE_LOCAL -->
<persistence-unit name="myPersistUnit" transaction-type="RESOURCE_LOCAL">
<!-- javax.persistence.PersistenceProvider接口的一個實作類 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- 顯式列出實體類,在Java SE 環境中應該顯式列出.也可以省略 -->
<class>com.haha.domain.User</class>
<!--廠商專有屬性(可選) 我們用的Hibernate,後面都是hibernate.cfg.xml中配置 -->
<properties>
<!-- 生成DDL的政策 -->
<property name="hibernate.hbm2ddl.auto" value="update" />
<!-- 資料庫的連接配接資訊 -->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/day04hibernate" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="root" />
<!-- 指定方言 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<!-- 是否顯示SQL語句 -->
<property name="hibernate.show_sql" value="true" />
<!-- 是否格式化SQL語句 -->
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
(4)、編寫一個工具類,用于擷取JPA的操作資料庫對象
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
//JPA的工具類
public class JpaUtils {
private static EntityManagerFactory em;
static{
em=Persistence.createEntityManagerFactory("myPersistUnit");
}
public static EntityManager createEntityManager(){
return em.createEntityManager();
}
}
(5)、編寫一個測試類 測試級聯儲存
import org.junit.Test;
import com.haha.domain.Role;
import com.haha.domain.User;
import com.haha.utils.JpaUtils;
public class demo2 {
/**
* 級聯儲存
*/
@Test
public void run1(){
EntityManager manager = JpaUtils.createEntityManager();
EntityTransaction tx = manager.getTransaction();
//開啟事務
tx.begin();
//增删改查操作
User u1=new User();
u1.setUname("哈哈");
User u2=new User();
u2.setUname("嘿嘿");
Role r1=new Role();
r1.setRname("歌手");
Role r2=new Role();
r2.setRname("ceo");
Role r3=new Role();
r3.setRname("演員");
//級聯儲存,外鍵維護
u1.getRoles().add(r1);
u1.getRoles().add(r2);
u2.getRoles().add(r3);
u2.getRoles().add(r1);
r1.getUsers().add(u1);
r1.getUsers().add(u2);
r2.getUsers().add(u1);
r3.getUsers().add(u2);
manager.persist(u1);
manager.persist(u2);
//送出事務
tx.commit();
}
}
另外他們中的其他操作的方法為: 查找:find(); 修改:merge() 删除:remove();
常用注解說明:
@Entity
作用:指定目前類是實體類。寫上此注解用于在建立SessionFactory時,加載映射配置。
@Table
作用:指定實體類和表之間的對應關系。
屬性:
name:指定資料庫表的名稱
@Id
作用:指定目前字段是主鍵。
@GeneratedValue
作用:指定主鍵的生成方式。JPA的主鍵生成方式詳解見2.4小節的說明。
屬性:
strategy :指定主鍵生成政策。JPA支援四種生成政策,具體介紹看2.4小節。
@Column
作用:指定實體類屬性和資料庫表之間的對應關系
屬性:
name:指定資料庫表的列名稱。
unique:是否唯一
nullable:是否可以為空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定義建表時建立此列的DDL
secondaryTable: 從表名。如果此列不建在主表上(預設建在主表),該屬性定義該列所在從表的名字
@OneToMany
作用:建立一對多的關系映射
屬性:
targetEntityClass:指定多的多方的類的位元組碼
mappedBy:指定從表實體類中引用主表對象的名稱。
cascade:指定要使用的級聯操作
fetch:指定是否采用延遲加載
orphanRemoval:是否使用孤兒删除
@ManyToOne
作用:建立多對一的關系
屬性:
targetEntityClass:指定一的一方實體類位元組碼
cascade:指定要使用的級聯操作
fetch:指定是否采用延遲加載
optional:關聯是否可選。如果設定為false,則必須始終存在非空關系。
@JoinColumn
作用:用于定義主鍵字段和外鍵字段的對應關系。
屬性:
name:指定外鍵字段的名稱
referencedColumnName:指定引用主表的主鍵字段名稱
unique:是否唯一。預設值不唯一
nullable:是否允許為空。預設值允許。
insertable:是否允許插入。預設值允許。
updatable:是否允許更新。預設值允許。
columnDefinition:列的定義資訊。
@ManyToMany
作用:用于映射多對多關系
屬性:
cascade:配置級聯操作。
fetch:配置是否采用延遲加載。
targetEntity:配置目标的實體類。映射多對多的時候不用寫。
@JoinTable
作用:針對中間表的配置
屬性:
name:配置中間表的名稱
joinColumns:中間表的外鍵字段關聯目前實體類所對應表的主鍵字段
inverseJoinColumn:中間表的外鍵字段關聯對方表的主鍵字段