天天看点

整合hibernate与JPA整合hibernate与JPA

整合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包到工程中。如下图

整合hibernate与JPA整合hibernate与JPA

(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:中间表的外键字段关联对方表的主键字段

继续阅读