欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

hibernate JPA学习

程序员文章站 2022-04-22 13:41:04
...

jpa环境搭建

第一步:拷贝Hibernate的全部jar包到工程中,并且加入jar实现包。

第二步:创建主配置文件

要求:在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_2_0.xsd"  
    version="2.0">  
    <!-- 配置持久化单元,可以配置多个,但是名称不能重复
    	name:用于指定持久化单元名称
    	transaction-type:指定事务的类型。
    			JTA:Java Transaction API
    			RESOURCE_LOCAL:指的是本地代码事务。(我们用这个)
    	
     -->
    <persistence-unit name="myJPAUnit" transaction-type="RESOURCE_LOCAL">
    	<!-- JPA规范的提供商 	可以不写。-->
    	<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    	<!-- 指定由Jpa注解的实体类位置 	可以不写。-->
    	<class>com.itheima.domain.Customer</class>
    	<!-- 连接库相关的一些配置,都是用hibernate的,所以只需要把之前hibernate主配置文件中的部分内容拷贝过来即可 -->
    	<properties>
    		<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
			<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/day58_ee287_jpa"/>
			<property name="hibernate.connection.username" value="root"/>
			<property name="hibernate.connection.password" value="1234"/>
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/><!-- 数据库的方言 -->
			<!-- 第二部分:hibernate的可选配置 -->
			<!-- 是否显示hibernate生成的SQL语句 -->
			<property name="hibernate.show_sql" value="true"/>
			<!-- 是否使用格式化输出sql语句到控制台 -->
			<property name="hibernate.format_sql" value="false"/>
			<!-- 配置hibernate采用何种方式生成DDL语句 -->
			<property name="hibernate.hbm2ddl.auto" value="update"/><!-- update表示检测实体类的映射配置和数据库的表结构是否一致,如果不一致,更新表结构 -->
			<!-- 设置hibernate的连接池提供商 -->
			<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"/>
    	</properties>
    </persistence-unit>
</persistence>

第三步:编写实体类并使用注解配置

package com.itheima.domain;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
 * 客户的实体类
 * @author zhy
 * 使用的注解都是JPA规范,所以导包,都需要导入javax.persistence包下的
 */
@Entity//表明该类是一个实体类
@Table(name="cst_customer")//建立当前类和数据库表的对应关系
public class Customer implements Serializable {
	
	@Id//表明当前字段是主键
	@Column(name="cust_id")//表明对应数据库的主键字段是cust_id
	//strategy:使用JPA中提供的主键生成策略。此属性用不了uuid。generator属性可以使用hibernate中的主键生成策略
	@GeneratedValue(strategy=GenerationType.IDENTITY)//指定主键生成策略。
	//声明一个主键生成器name属性:给生成器起个名字。strategy:指定的就是hibernate中包含的生成策略
	//@GenericGenerator(name="uuid",strategy="uuid")
	//@GeneratedValue(generator="uuid")
	private Long custId;
	
	@Column(name="cust_name")
	private String custName;
	
	@Column(name="cust_source")
	private String custSource;
	
	@Column(name="cust_industry")
	private String custIndustry;
	
	@Column(name="cust_level")
	private String custLevel;
	
	@Column(name="cust_address")
	private String custAddress;
	
	@Column(name="cust_phone")
	private String custPhone;

}

第四步:编写工具类,用于获取JPA的操作数据库对象

public final class JPAUtil {
	//JPA的实体管理器工厂:相当于Hibernate的SessionFactory
	private static EntityManagerFactory em;
	//使用静态代码块赋值
	static {
		//注意:该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致
		em = Persistence.createEntityManagerFactory("myPersistUnit");
	}

	/**
	 * 使用管理器工厂生产一个管理器对象
	 * @return
	 */
	public static EntityManager getEntityManager() {
		return em.createEntityManager();
	}
}

jpa入门案例

@Test
	public void testAdd() {
		// 定义对象
		Customer c = new Customer();
		c.setCustName("传智学院");
		// 获取实体管理对象
		EntityManager em = JpaUtils.getEntityManager();
		// 获取事务对象
		EntityTransaction tx = em.getTransaction();
		// 开启事务
		tx.begin();
		// 执行操作
		em.persist(c);
		// 提交事务
		tx.commit();
		// 释放资源
		em.close();
	}

JPA的CRUD操作

查询一个

//立即加载不能修改为延迟
Customer c = em.find(Customer.class, 1L);
//延迟加载不能修改为立即
Customer c1 = em.getReference(Customer.class, 112l);

查询所有
JPQL的写法:
* 表名使用实体类名称替代
* 列名使用实体类属性名称替代
* 不能使用*号。查询所有,需要在from关键字后面的类名上加别名
* 例如: select c from Customer c
* 查询条件可以使用?作为参数占位符。
* 给占位符赋值时,占位符索引位置从1开始
* 获取结果集的方法
* getResultList():查询结果是一个List集合
* getSingleResult():查询结果是一个对象

Query query = em.createQuery("select c from Customer c where custName like ? ");
query.setParameter(1,"%学院%");
List list = query.getResultList();

更新一个
当一个session保存具有相同的oid对象时
直接用hibernate的update会报错;
这时我们用em.merge(ustomer)

Customer c = em.find(Customer.class, 1L);
c.setCustName("江苏传智学院");
//提交事务
tx.commit();  //使用JPA中快照机制实现更新

删除一个

Customer c = em.find(Customer.class, 6L);
em.remove(c);

JPA的多表映射

一对多关系映射

客户配置

@OneToMany(targetEntity=LinkMan.class,mappedBy="customer"//放弃维护关联关系)
private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);

联系人配置

@ManyToOne(targetEntity=Customer.class)
@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
private Customer customer;//用它的主键,对应联系人表中的外键

保存操作

创建一个客户和一个联系人
建立客户和联系人的双向关联关系

先保存客户,再保存联系人,保存成功
如果只保存客户,没级联,因为客户放弃维护关联关系,就只保存了客户
有级联则保存成功
如果只保存联系人,有级联则保存成功,
没有级联则保存失败,因为持久态对象关联一个临时态,请先保存临时态

更新操作

创建一个联系人
查询id为5的客户
为5这个客服分配该联系人

更新客户 放弃维护关联关系,运行成功,数据库没变化
更新客户 不放弃维护关联关系,报错,因为持久态对象关联一个临时态,请先保存临时态
这时需要级联保存cascade=CascadeType.PERSIST

删除操作

删除客户
如果客户放弃维护关联关系,删除报错,因为客户放弃关联关系就不会修改外键为null
如果客户不放弃维护关联关系,删除成功,外键修改为null;
或者级联删除

查询操作

它可以使用对象导航的方式customer.getLinkmans()
一的一方默认懒加载,fetch=FetchType.EAGER立即加载,
多的一方默认立即加载

多对多关系映射

用户配置
用户和角色俩配置可以互换

@ManyToMany(mappedBy="users",cascade=CascadeType.ALL)
private Set<SysRole> roles = new HashSet<SysRole>(0);

角色配置

@ManyToMany(cascade=CascadeType.ALL)
	//加入一张表
	@JoinTable(name="user_role_ref",
			  joinColumns={@JoinColumn(name="role_id",referencedColumnName="role_id")},//写的是当前实体在中间表的外键字段
			  inverseJoinColumns={@JoinColumn(name="user_id",referencedColumnName="user_id")}//写的是对方实体在中间表的外键字段
	)
	private Set<SysUser> users = new HashSet<SysUser>(0);

保存操作

如果只保存用户,没级联,因为用户放弃维护关联关系,就只保存了用户
有级联则成功
如果只保存角色,有级联则保存成功,
没有级联则保存失败

删除操作

多对多都不能配置级联删除

JPA中使用c3p0连接池

和hibernate中使用方法一样

把EntityManager和线程绑定

1.与spring整合
暂时不讲
2.当事务类型为JTA时
这个方法可以,好像不怎么用

entityManagerFactory.createEntityManager(SynchronizationType.SYNCHRONIZED);

3.自己手写

private static EntityManagerFactory entityManagerFactory;
	private static ThreadLocal<EntityManager> EntityManager = new ThreadLocal<>();
	static {
		entityManagerFactory = Persistence.createEntityManagerFactory("myJPAUnit");
	}
	public static EntityManager getTLEntityManager() {
		EntityManager entityManager = EntityManager.get();
		if (entityManager == null) {
			entityManager = entityManagerFactory.createEntityManager();
			EntityManager.set(entityManager);
		}
		return EntityManager.get();
	}
}

hibernate中使用jpa注解映射配置

只需这一步就OK
<!–第三部分:映射配置文件的位置–>

<mapping class="com.itheima.domain.Customer"/>