SSH框架之Hibernate第四篇

  • 2019 年 10 月 5 日
  • 笔记

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/zhao1299002788/article/details/100623070

Hibernate中有两套实现数据库数据操作的方式 :  		hibernate前3天讲解的都是 : hibernate自己的操作方式(纯XML配置文件的方式)  		另一种方式是基于JPA的操作方式(通过注解的方式替代之前的部分XML)    	JPA相关概念:  		1.1JPA概述 : (java的持久化规范(规范即接口))  			全称是 : Java Persistence API. 是SUN公司推出的一套基于ORM的规范.hibernate框架中提供了JPA的实现.  			JAP通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.  		1.2JPA要明确的  			a. JPA是一套ORM规范(算是一个接口),hibernate实现了JPA规范(算是一个实现类).  			b. hibernate中有自己的独立ORM操作数据库方式,也有JPA规范实现的操作数据库方式.  			c. 在数据库增删改查操作中,我们hibernate和JPA的操作都要会.  		JPA和hibernate的关系?  			JPA是接口,hibernate是实现.  			所有的ORM框架都可以去实现JPA接口,通过JPA提供的一些接口来操作数据库的数据.    		JPA的使用 :  			JPA是通过注解的方式来描述,对象和表的映射关系.  			之前的对象和表的映射关系配置是通过XML,今天要替换成注解的方式.    		注释 : 给程序员看的.  		注解 : 给程序来使用的.  			为什么要出现注解?  				一开始就是为了替代所有的XML配置文件.    				工作中两种方式结合使用 :  					配置文件 + 注解  						如果是需要常常改动的程序 : 用配置文件.  						如果是定义好了不需要更改的程序 : 注解.    	2.1 2 JPA的环境搭建  		1 hibernate的环境(16个包)  		2 JPA的环境(1个包)    		2.2.2 创建配置文件  				要求:在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">    					  <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/hibernate_jpa"/>  							   <property name="hibernate.connection.username" value="root" />  							   <property name="hibernate.connection.password" value="1234" />  							   <!-- 指定方言 -->  							   <property name="hibernate.dialect"  										value="org.hibernate.dialect.MySQL5Dialect" />  							   <!-- 是否显示SQL语句 -->  							   <property name="hibernate.show_sql" value="false" />  							   <!-- 是否格式化SQL语句 -->  							   <property name="hibernate.format_sql" value="true" />  						</properties>  					</persistence-unit>  				</persistence>    		2.2.3 编写工具类,用于获取JPA的操作数据库对象  			public class HibernateUtils {  				//JPA的实体管理器工厂 : 相当于Hibernate的SessionFactory  				private static EntityManagerFactory em;  				//使用静态代码块赋值  				static {  					//加载一次配置文件  					//注意 : 该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致  					em = Persistence.createEntityManagerFactory("aaa");  				}  				/*  				 * 使用管理器工厂生产一个管理器对象  				 */  				//相当于获取连接  				public static EntityManager getEntityManager() {  					return em.createEntityManager();  				}  			}    		jpa 的批量查询方式 :  			类似咋们之前学习的query方式查询 :  				1 : qr.getResultList() ;  类似之前的qr.list();  				2 : hibernate对于占位符?    以前是从0开始,jpa是从1开始.  				3 : 聚合 qr.getSingleResult();   类似之前的uniqueResult();    		2.2.4 编写实体类,并使用注解配置  			//级联保存 (保存客户的同时把关联的联系人给保存了)  			//jpa的注解里面 @OneToMany  添加属性cascade = CascadeType.PERSIST_STORE  			//根据一的一方保存多的一方的数据.  			// 级联保存 (保存联系人的同时把关联的客户给保存了)  			// jpa的注解里面 @ManyToOne  添加属性cascade=CascadeType.PERSIST  			//jpa的一对多没有普通删除  			// 级联删除  			// jpa的注解里面 @OneToMany  添加属性cascade=CascadeType.REMOVE (All)    			/**  			 * 客户的实体类  			 */  			@Entity  			@Table(name="cst_customer")  			public class Customer implements Serializable {    				@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_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;    				public Long getCustId() {  					return custId;  				}  				public void setCustId(Long custId) {  					this.custId = custId;  				}  				public String getCustName() {  					return custName;  				}  				public void setCustName(String custName) {  					this.custName = custName;  				}  				public String getCustSource() {  					return custSource;  				}  				public void setCustSource(String custSource) {  					this.custSource = custSource;  				}  				public String getCustIndustry() {  					return custIndustry;  				}  				public void setCustIndustry(String custIndustry) {  					this.custIndustry = custIndustry;  				}  				public String getCustLevel() {  					return custLevel;  				}  				public void setCustLevel(String custLevel) {  					this.custLevel = custLevel;  				}  				public String getCustAddress() {  					return custAddress;  				}  				public void setCustAddress(String custAddress) {  					this.custAddress = custAddress;  				}  				public String getCustPhone() {  					return custPhone;  				}  				public void setCustPhone(String custPhone) {  					this.custPhone = custPhone;  				}  				@Override  				public String toString() {  					return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource  							+ ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress  							+ ", custPhone=" + custPhone + "]";  				}  			}    		2.3 常用注解说明  			@Entity  				作用 : 指定当前类是实体类.写上此注解用于在创建SessionFactory/EntityManager时,加载映射配置.    			@Table  				作用 : 指定实体类和表之间的对应关系.  				属性 :  					name : 指定数据库表的名称.    			@Id  				作用 : 指定当前字段是主键.    			@GeneratedValue  				作用 : 指定主键的生成方式.JPA的主键生成方式  				属性 :  					strategy : 指定主键生成策略.JPA支持四种生成策略,    			@Column :  				作用 : 指定实体类属性和数据库表之间的对应关系.  				属性 :  					name : 指定数据库表的列名称.  					unique : 是否唯一 .  					nullable : 是否可以为空  					inserttable : 是否可以插入  					updateable : 是否可以更新  					columnDefinition : 定义建表时创建此列的DDL.  					secondaryTable : 从表名.如果此列不建在主表上(默认键在主表),该属性定义该列所在从表的名字.  			2.4主键生成策略  				通过annotation(注解)来映射hibernate实体的,基于annotation的hibernate主键标识为@Id,  				其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法。  				JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO。具体说明如下:  				2.4.1IDENTITY:主键由数据库自动生成(主要是自动增长型)  				用法:  					@Id  					@GeneratedValue(strategy = GenerationType.IDENTITY)  					private Long custId;  				2.4.2SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。  				用法:  					@Id  					@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="payablemoney_seq")  					@SequenceGenerator(name="payablemoney_seq", sequenceName="seq_payment")  				说明:  					@SequenceGenerator源码中的定义  					@Target({TYPE, METHOD, FIELD})  					@Retention(RUNTIME)  					public @interface SequenceGenerator {  						String name();  				 		String sequenceName() default "";  				 		int initialValue() default 0;  				 		int allocationSize() default 50;  					}  				name:表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中。  					sequenceName:属性表示生成策略用到的数据库序列名称。  					initialValue:表示主键初识值,默认为0。  					allocationSize:表示每次主键值增加的大小,例如设置1,则表示每次插入新记录后自动加1,默认为50。    				2.4.3AUTO:主键由程序控制。  				用法:  					@Id  					@GeneratedValue(strategy = GenerationType.AUTO)      				2.5JPA的CRUD操作  				2.5.1保存  				/**  					 * 保存一个实体  					 */  					@Test  					public void testAdd(){  						//定义对象  						Customer c = new Customer();  						c.setCustName("传智学院");  						c.setCustLevel("VIP客户");  						c.setCustSource("网络");  						c.setCustIndustry("IT教育");  						c.setCustAddress("昌平区北七家镇");  						c.setCustPhone("010-84389340");  						EntityManager em=null;  						EntityTransaction tx=null;  						try{  							//获取实体管理对象  							em=JPAUtil.getEntityManager();  							//获取事务对象  							tx=em.getTransaction();  							//开启事务  							tx.begin();  							//执行操作  							em.persist(c);  							//提交事务  							tx.commit();  						}catch(Exception e){  							//回滚事务  							tx.rollback();  							e.printStackTrace();  						}finally{  							//释放资源  							em.close();  						}  					}    				2.5.2修改  					/**  					 * 修改  					 */  					@Test  					public void testUpdate(){  						//定义对象  						EntityManager em=null;  						EntityTransaction tx=null;  						try{  							//获取实体管理对象  							em=JPAUtil.getEntityManager();  							//获取事务对象  							tx=em.getTransaction();  							//开启事务  							tx.begin();  							//执行操作  							Customer c1 = em.find(Customer.class, 1L);  							c1.setCustName("江苏传智学院");  							//提交事务  							tx.commit();  //使用JPA中快照机制实现更新  						}catch(Exception e){  							//回滚事务  							tx.rollback();  							e.printStackTrace();  						}finally{  							//释放资源  							em.close();  						}  					}    				merge方法实现修改  					@Test  					public void testMerge(){  						//定义对象  						EntityManager em=null;  						EntityTransaction tx=null;  						try{  							//获取实体管理对象  							em=JPAUtil.getEntityManager();  							//获取事务对象  							tx=em.getTransaction();  							//开启事务  							tx.begin();  							//执行操作  							Customer c1 = em.find(Customer.class, 6L);  							c1.setCustName("江苏传智学院");  							em.clear();//把c1对象从缓存中清除出去  							em.merge(c1);  							//提交事务  							tx.commit();  						}catch(Exception e){  							//回滚事务  							tx.rollback();  							e.printStackTrace();  						}finally{  							//释放资源  							em.close();  						}  					}  				2.5.3删除  					/**  					 * 删除  					 */  					@Test  					public void testRemove(){  						//定义对象  						EntityManager em=null;  							EntityTransaction tx=null;  							try{  								//获取实体管理对象  								em=JPAUtil.getEntityManager();  								//获取事务对象  								tx=em.getTransaction();  								//开启事务  								tx.begin();  								//执行操作  								Customer c1 = em.find(Customer.class, 6L);  								em.remove(c1);  								//提交事务  								tx.commit();  							}catch(Exception e){  								//回滚事务  								tx.rollback();  								e.printStackTrace();  							}finally{  								//释放资源  								em.close();  							}  					}  				2.5.4查询一个  					/**  					 * 查询一个:  					 * 	使用立即加载的策略  					 */  					@Test  					public void testGetOne(){  						//定义对象  						EntityManager em=null;  							EntityTransaction tx=null;  						 try{  								//获取实体管理对象  								em=JPAUtil.getEntityManager();  								//获取事务对象  								tx=em.getTransaction();  								//开启事务  								tx.begin();  								//执行操作  								Customer c1 = em.find(Customer.class, 1L);  								//提交事务  								tx.commit();  								System.out.println(c1); //输出查询对象  						 }catch(Exception e){  								//回滚事务  								tx.rollback();  								e.printStackTrace();  							}finally{  								//释放资源  								em.close();  							}  					}    				查询实体的缓存问题  				@Test  					public void testGetOne(){  						//定义对象  						EntityManager em=null;  						EntityTransaction tx=null;  						try{  							//获取实体管理对象  							em=JPAUtil.getEntityManager();  							//获取事务对象  							tx=em.getTransaction();  							//开启事务  							tx.begin();  							//执行操作  							Customer c1 = em.find(Customer.class, 1L);  							Customer c2 = em.find(Customer.class, 1L);  							System.out.println(c1 == c2);//输出结果是true,EntityManager也有缓存  							//提交事务  							tx.commit();  							System.out.println(c1);  						}catch(Exception e){  							//回滚事务  							tx.rollback();  							e.printStackTrace();  						}finally{  							//释放资源  							em.close();  						}  					}    				延迟加载策略的方法:  					/**  					 * 查询一个:  					 * 	使用延迟加载策略  					 */  					@Test  					public void testLoadOne(){  						//定义对象  						EntityManager em=null;  						EntityTransaction tx=null;  						try{  							//获取实体管理对象  							em=JPAUtil.getEntityManager();  							//获取事务对象  							tx=em.getTransaction();  							//开启事务  							tx.begin();  							//执行操作  							Customer c1 = em.getReference(Customer.class, 1L);  							//提交事务  							tx.commit();  							System.out.println(c1);  						}catch(Exception e){  							//回滚事务  							tx.rollback();  							e.printStackTrace();  						}finally{  							//释放资源  							em.close();  						}  					}  				2.5.5查询所有  					/**  					 * 查询所有  					 * 	涉及的对象:  					 * 		Query(注意:不是Hibernate的Query)  					 *  	如何获取:  					 *  		使用EntityManager的createQuery(String JPQL)方法;  					 *  	参数的含义  					 *  		JPQL:jpa  query language  					 *  		JPQL的写法:  					 *  		表名使用实体类名称替代  					 *  		列名使用实体类属性名称替代  					 *  		不能使用*号。查询所有,需要在from关键字后面的类名上加别名  					 *  		例如: select c from Customer c  					 *  		查询条件可以使用?作为参数占位符。  					 *  		给占位符赋值时,占位符索引位置从1开始  					 *	获取结果集的方法  					 *		getResultList():查询结果是一个List集合  					 * 		getSingleResult():查询结果是一个对象  					 */  					@Test  					public void testFindAll(){  						//定义对象  						EntityManager em=null;  						EntityTransaction tx=null;  						try{  							//获取实体管理对象  							em=JPAUtil.getEntityManager();  							//获取事务对象  							tx=em.getTransaction();  							//开启事务  							tx.begin();  							//执行操作  							Query query = em.createQuery("select c from Customer c where custName like ? ");  							query.setParameter(1,"%学院%");  							List list = query.getResultList();  							//提交事务  							tx.commit();    							for(Object o : list){  								System.out.println(o);  							}  						}catch(Exception e){  							//回滚事务  							tx.rollback();  							e.printStackTrace();  						}finally{  							//释放资源  							em.close();  						}  					}    		3.1一对多关系映射  			3.1.1常用注解  			3.1.1.1@OneToMany:  			作用:  				建立一对多的关系映射  			属性:  				targetEntityClass:指定多的方的类的字节码  				mappedBy:指定从表实体类中引用主表对象的名称。  				cascade:指定要使用的级联操作  				fetch:指定是否采用延迟加载  				orphanRemoval:是否使用孤儿删除  			3.1.1.2@ManyToOne  			作用:  				建立多对一的关系  			属性:  				targetEntityClass:指定一的一方实体类字节码  				cascade:指定要使用的级联操作  				fetch:指定是否采用延迟加载  				optional:关联是否可选。如果设置为false,则必须始终存在非空关系。  			3.1.1.3@JoinColumn  			作用:  				用于定义主键字段和外键字段的对应关系。  			属性:  				name:指定外键字段的名称  				referencedColumnName:指定引用主表的主键字段名称  				unique:是否唯一。默认值不唯一  				nullable:是否允许为空。默认值允许。  				insertable:是否允许插入。默认值允许。  				updatable:是否允许更新。默认值允许。  				columnDefinition:列的定义信息。  			3.1.2配置代码  			3.1.2.1客户配置  			/**  			 * 客户的实体类  			 * 明确使用的注解都是JPA规范的  			 * 所以导包都要导入javax.persistence包下的  			 *  			 */  			@Entity//表示当前类是一个实体类  			@Table(name="cst_customer")//建立当前实体类和表之间的对应关系  			public class Customer implements Serializable {    				@Id//表明当前私有属性是主键  				@GeneratedValue(strategy=GenerationType.IDENTITY)//指定主键的生成策略  				@Column(name="cust_id")//指定和数据库表中的cust_id列对应  				private Long custId;  				@Column(name="cust_name")//指定和数据库表中的cust_name列对应  				private String custName;  				@Column(name="cust_source")//指定和数据库表中的cust_source列对应  				private String custSource;  				@Column(name="cust_industry")//指定和数据库表中的cust_industry列对应  				private String custIndustry;  				@Column(name="cust_level")//指定和数据库表中的cust_level列对应  				private String custLevel;  				@Column(name="cust_address")//指定和数据库表中的cust_address列对应  				private String custAddress;  				@Column(name="cust_phone")//指定和数据库表中的cust_phone列对应  				private String custPhone;    				@OneToMany(targetEntity=LinkMan.class,mappedBy="customer")  				private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);    				public Long getCustId() {  					return custId;  				}  				public void setCustId(Long custId) {  					this.custId = custId;  				}  				public String getCustName() {  					return custName;  				}  				public void setCustName(String custName) {  					this.custName = custName;  				}  				public String getCustSource() {  					return custSource;  				}  				public void setCustSource(String custSource) {  					this.custSource = custSource;  				}  				public String getCustIndustry() {  					return custIndustry;  				}  				public void setCustIndustry(String custIndustry) {  					this.custIndustry = custIndustry;  				}  				public String getCustLevel() {  					return custLevel;  				}  				public void setCustLevel(String custLevel) {  					this.custLevel = custLevel;  				}  				public String getCustAddress() {  					return custAddress;  				}  				public void setCustAddress(String custAddress) {  					this.custAddress = custAddress;  				}  				public String getCustPhone() {  					return custPhone;  				}  				public void setCustPhone(String custPhone) {  					this.custPhone = custPhone;  				}  				public Set<LinkMan> getLinkmans() {  					return linkmans;  				}  				public void setLinkmans(Set<LinkMan> linkmans) {  					this.linkmans = linkmans;  				}  				@Override  				public String toString() {  					return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource  							+ ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress  							+ ", custPhone=" + custPhone + "]";  				}  			}  			3.1.2.2联系人配置  			/**  			 * 联系人的实体类(数据模型)  			*/  			@Entity  			@Table(name="cst_linkman")  			public class LinkMan implements Serializable {  				@Id  				@GeneratedValue(strategy=GenerationType.IDENTITY)  				@Column(name="lkm_id")  				private Long lkmId;  				@Column(name="lkm_name")  				private String lkmName;  				@Column(name="lkm_gender")  				private String lkmGender;  				@Column(name="lkm_phone")  				private String lkmPhone;  				@Column(name="lkm_mobile")  				private String lkmMobile;  				@Column(name="lkm_email")  				private String lkmEmail;  				@Column(name="lkm_position")  				private String lkmPosition;  				@Column(name="lkm_memo")  				private String lkmMemo;    				//多对一关系映射:多个联系人对应客户  				@ManyToOne(targetEntity=Customer.class)  				@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")  				private Customer customer;//用它的主键,对应联系人表中的外键    				public Long getLkmId() {  					return lkmId;  				}  				public void setLkmId(Long lkmId) {  					this.lkmId = lkmId;  				}  				public String getLkmName() {  					return lkmName;  				}  				public void setLkmName(String lkmName) {  					this.lkmName = lkmName;  				}  				public String getLkmGender() {  					return lkmGender;  				}  				public void setLkmGender(String lkmGender) {  					this.lkmGender = lkmGender;  				}  				public String getLkmPhone() {  					return lkmPhone;  				}  				public void setLkmPhone(String lkmPhone) {  					this.lkmPhone = lkmPhone;  				}  				public String getLkmMobile() {  					return lkmMobile;  				}  				public void setLkmMobile(String lkmMobile) {  					this.lkmMobile = lkmMobile;  				}  				public String getLkmEmail() {  					return lkmEmail;  				}  				public void setLkmEmail(String lkmEmail) {  					this.lkmEmail = lkmEmail;  				}  				public String getLkmPosition() {  					return lkmPosition;  				}  				public void setLkmPosition(String lkmPosition) {  					this.lkmPosition = lkmPosition;  				}  				public String getLkmMemo() {  					return lkmMemo;  				}  				public void setLkmMemo(String lkmMemo) {  					this.lkmMemo = lkmMemo;  				}  				public Customer getCustomer() {  					return customer;  				}  				public void setCustomer(Customer customer) {  					this.customer = customer;  				}  				@Override  				public String toString() {  					return "LinkMan [lkmId=" + lkmId + ", lkmName=" + lkmName + ", lkmGender=" + lkmGender + ", lkmPhone="  							+ lkmPhone + ", lkmMobile=" + lkmMobile + ", lkmEmail=" + lkmEmail + ", lkmPosition=" + lkmPosition  							+ ", lkmMemo=" + lkmMemo + "]";  				}  			}  			3.2多对多关系映射  			3.2.1常用注解:  			3.2.1.1@ManyToMany  			作用:  				用于映射多对多关系  			属性:  				cascade:配置级联操作。  				fetch:配置是否采用延迟加载。  				targetEntity:配置目标的实体类。映射多对多的时候不用写。  			3.2.1.2@JoinTable  			作用:  				针对中间表的配置  			属性:  				name:配置中间表的名称  				joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段  				inverseJoinColumn:中间表的外键字段关联对方表的主键字段    			3.2.1.3@JoinColumn  			作用:  				用于定义主键字段和外键字段的对应关系。  			属性:  				name:指定外键字段的名称  				referencedColumnName:指定引用主表的主键字段名称  				unique:是否唯一。默认值不唯一  				nullable:是否允许为空。默认值允许。  				insertable:是否允许插入。默认值允许。  				updatable:是否允许更新。默认值允许。  				columnDefinition:列的定义信息。    			3.2.2配置代码  			3.2.2.1用户配置  			/**  			 * 用户的数据模型  			*/  			@Entity  			@Table(name="sys_user")  			public class SysUser implements Serializable {    				@Id  				@GeneratedValue(strategy=GenerationType.IDENTITY)  				@Column(name="user_id")  				private Long userId;  				@Column(name="user_code")  				private String userCode;  				@Column(name="user_name")  				private String userName;  				@Column(name="user_password")  				private String userPassword;  				@Column(name="user_state")  				private String userState;    				//多对多关系映射  				@ManyToMany(mappedBy="users")  				private Set<SysRole> roles = new HashSet<SysRole>(0);    				public Long getUserId() {  					return userId;  				}  				public void setUserId(Long userId) {  					this.userId = userId;  				}  				public String getUserCode() {  					return userCode;  				}  				public void setUserCode(String userCode) {  					this.userCode = userCode;  				}  				public String getUserName() {  					return userName;  				}  				public void setUserName(String userName) {  					this.userName = userName;  				}  				public String getUserPassword() {  					return userPassword;  				}  				public void setUserPassword(String userPassword) {  					this.userPassword = userPassword;  				}  				public String getUserState() {  					return userState;  				}  				public void setUserState(String userState) {  					this.userState = userState;  				}  				public Set<SysRole> getRoles() {  					return roles;  				}  				public void setRoles(Set<SysRole> roles) {  					this.roles = roles;  				}  				@Override  				public String toString() {  					return "SysUser [userId=" + userId + ", userCode=" + userCode + ", userName=" + userName + ", userPassword="  							+ userPassword + ", userState=" + userState + "]";  				}  			}      			3.2.2.2角色配置  			/**  			 * 角色的数据模型  			*/  			@Entity  			@Table(name="sys_role")  			public class SysRole implements Serializable {    				@Id  				@GeneratedValue(strategy=GenerationType.IDENTITY)  				@Column(name="role_id")  				private Long roleId;  				@Column(name="role_name")  				private String roleName;  				@Column(name="role_memo")  				private String roleMemo;    				//多对多关系映射  				@ManyToMany  				@JoinTable(name="user_role_rel",//中间表的名称  						  //中间表user_role_rel字段关联sys_role表的主键字段role_id  				joinColumns={@JoinColumn(name="role_id",referencedColumnName="role_id")},  						  //中间表user_role_rel的字段关联sys_user表的主键user_id  				inverseJoinColumns={@JoinColumn(name="user_id",referencedColumnName="user_id")}  				)  				private Set<SysUser> users = new HashSet<SysUser>(0);      				public Long getRoleId() {  					return roleId;  				}  				public void setRoleId(Long roleId) {  					this.roleId = roleId;  				}  				public String getRoleName() {  					return roleName;  				}  				public void setRoleName(String roleName) {  					this.roleName = roleName;  				}  				public String getRoleMemo() {  					return roleMemo;  				}  				public void setRoleMemo(String roleMemo) {  					this.roleMemo = roleMemo;  				}  				public Set<SysUser> getUsers() {  					return users;  				}  				public void setUsers(Set<SysUser> users) {  					this.users = users;  				}  				@Override  				public String toString() {  					return "SysRole [roleId=" + roleId + ", roleName=" + roleName + ", roleMemo=" + roleMemo + "]";  				}      			}      			第4章JPA的多表操作  			4.1一对多关系的增删改操作  			4.1.1保存操作  			保存原则:先保存主表,再保存从表。  				/**  				 * 保存操作  				 * 需求:  				 * 	保存一个客户和一个联系人  				 * 要求:  				 * 	创建一个客户对象和一个联系人对象  				 *  建立客户和联系人之间关联关系(双向一对多的关联关系)  				 *  先保存客户,再保存联系人  				 */  				@Test  				public void test1(){  					//创建客户和联系人对象  					Customer c = new Customer();//瞬时态  					c.setCustName("TBD云集中心");  					c.setCustLevel("VIP客户");  					c.setCustSource("网络");  					c.setCustIndustry("商业办公");  					c.setCustAddress("昌平区北七家镇");  					c.setCustPhone("010-84389340");    					LinkMan l = new LinkMan();//瞬时态  					l.setLkmName("TBD联系人");  					l.setLkmGender("male");  					l.setLkmMobile("13811111111");  					l.setLkmPhone("010-34785348");  					l.setLkmEmail("[email protected]");  					l.setLkmPosition("老师");  					l.setLkmMemo("还行吧");    					//建立他们的双向一对多关联关系  					l.setCustomer(c);  					c.getLinkmans().add(l);  					//获取JPA操作对照  					EntityManager em = JPAUtil.getEntityManager();  					//获取JPA事务对象  					EntityTransaction tx= em.getTransaction();  						//开启事务  						tx.begin();  					//按照要求:先保存客户,再保存联系人(此时符合保存原则:先保存主表,再保存从表)  					em.persist(c);  					em.persist(l);  					tx.commit();  				}    			JPA注解的配置方式:不涉及多一条update语句的问题  			4.1.2删除操作  				/**  				 * 删除操作  				 * 	删除从表数据:可以随时任意删除。  				 * 	删除主表数据:  				 * 		有从表数据引用  				 * 			1、不能删除  				 * 			2、如果还想删除,使用级联删除  				 * 		没有从表数据引用:随便删  				 *  				 * 在实际开发中,级联删除请慎用!(在一对多的情况下)  				 */  				@Test  				public void test3(){  					//获取JPA操作对照  					EntityManager em = JPAUtil.getEntityManager();  					//获取JPA事务对象  					EntityTransaction tx= em.getTransaction();  						//开启事务  						tx.begin();  					//查询id为1的客户  					Customer c1 = em.find(Customer.class, 2L);  					//删除id为1的客户  					em.remove(c1);  					tx.commit();  				}    			级联删除的配置:  			@OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.ALL) //用CascadeType.REMOVE也可以  			private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);  			4.2多对多关系的增删操作  			4.2.1保存操作  				/**  				 * 需求:  				 * 	保存用户和角色  				 * 要求:  				 * 	创建2个用户和3个角色  				 * 	让1号用户具有1号和2号角色(双向的)  				 * 	让2号用户具有2号和3号角色(双向的)  				 *  保存用户和角色  				 */  				@Test  				public void test1(){  					//创建对象  					SysUser u1 = new SysUser();  					u1.setUserName("用户1");  					SysUser u2 = new SysUser();  					u2.setUserName("用户2");    					SysRole r1 = new SysRole();  					r1.setRoleName("角色1");  					SysRole r2 = new SysRole();  					r2.setRoleName("角色2");  					SysRole r3 = new SysRole();  					r3.setRoleName("角色3");    					//建立关联关系  					u1.getRoles().add(r1);  					u1.getRoles().add(r2);  					r1.getUsers().add(u1);  					r2.getUsers().add(u1);    					u2.getRoles().add(r2);  					u2.getRoles().add(r3);  					r2.getUsers().add(u2);  					r3.getUsers().add(u2);    					//获取JPA操作对照  					EntityManager em = JPAUtil.getEntityManager();  					//获取JPA事务对象  					EntityTransaction tx= em.getTransaction();  						//开启事务  						tx.begin();  					em.persist(u1);  					em.persist(u2);  					em.persist(r1);  					em.persist(r2);  					em.persist(r3);  					tx.commit();  				}    			JPA注解的配置方式:不涉及保存失败的问题:  			4.2.2删除操作  				/**  				 * 删除操作  				 * 	在多对多的删除时,双向级联删除根本不能配置  				 * 禁用  				 *	如果配了的话,如果数据之间有相互引用关系,可能会清空所有数据  				 */  				@Test  				public void test2(){  					//获取JPA操作对照  					EntityManager em = JPAUtil.getEntityManager();  					//获取JPA事务对象  					EntityTransaction tx= em.getTransaction();  						//开启事务  						tx.begin();  					SysUser u1 = em.find(SysUser.class,3L);  					em.remove(u1);  					tx.commit();  				}    			在多对多映射配置中不能出现双向级联删除的配置,无论注解还是XML配置    		5.2JPA和hibernate中操作数据的方法对照  			操作	Hibernate中的方法	JPA中的方法	说明  			保存操作	save(Object entity)	persist(Object entity)	共同点:都是把临时态对象转成了持久态。  			区别:  			提供者不一样:  				save方法是hibernate提供的。  				persist方法是JPA规范提供的。  			在没有事务的情况下:  				save会去数据库中保存,hibernate提供了一个内置的事务来执行。  				persist什么都不会做。  			更新操作	update (Object entity)	merge (Object entity)	Hibernate和jpa都可以利用快照机制,不调用任何方法去更新。  			Update方法在更新时,如果遇到一级缓存已经包含了一个相同OID的对象会报错。merge则可以执行成功。  			删除操作	delete (Object entity)	remove (Object entity)	都是删除一个实体  			查询一个操作	get (Class clazz,Serializable id)  			load(Class clazz,Serializable id)	find(Class clazz,Object id)  			getReerence(Class clazz,Object id)	get和find都是立即加载。load和getReference一样都是延迟加载。  			查询所有操作	Query:使用HQL语句查询	Query:使用JPQL查询	查询语句的形式不一样。  			查询返回唯一结果操作	uniqueResult()	getSingleResult()	查询都是返回一个唯一的结果。    		JPA一对多的注解配置:  			案例:  				// ps: jpa提供的注解都在:javax.persistence包下  				@Entity  				@Table(name="cst_customer")  				public  class Customer  				{  					@Id  					@Column(name="cust_id")  					@GeneratedValue(strategy=GenerationType.IDENTITY)  					private Long cust_id; // '客户编号(主键)',    					@Column(name="cust_name")  					private String cust_name; // '客户名称(公司名称)',    					@Column(name="cust_source")  					private String cust_source; // '客户信息来源',    					@Column(name="cust_industry")  					private String cust_industry; // '客户所属行业',    					@Column(name="cust_level")  					private String cust_level; // '客户级别',    					@Column(name="cust_address")  					private String cust_address; // '客户联系地址',    					@Column(name="cust_phone")  					private String cust_phone; // '客户联系电话    					// 有多的一方的集合  					/*targetEntity:对方的类型  					 * mappedBy:自己在对方里的属性名称   (mappedBy写在哪方,哪方意味着放弃外键的维护)  					 *  					 * */  					@OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE)  					private Set<LinkMan> linkmans=new HashSet();    					@Entity  					@Table(name="cst_linkman")  					public class LinkMan  					{  						@Id  						@Column(name="lkm_id")  						@GeneratedValue(strategy=GenerationType.IDENTITY)  						private Long lkm_id;// '联系人编号(主键)',    						@Column(name="lkm_name")  						private String lkm_name;// '联系人姓名',    						@Column(name="lkm_gender")  						private String lkm_gender;// '联系人性别',    						@Column(name="lkm_phone")  						private String lkm_phone;// '联系人办公电话',    						@Column(name="lkm_mobile")  						private String lkm_mobile;// '联系人手机',    						@Column(name="lkm_email")  						private String lkm_email;// '联系人邮箱',    						@Column(name="lkm_qq")  						private String lkm_qq;// '联系人qq',    						@Column(name="lkm_position")  						private String lkm_position;// '联系人职位',    						@Column(name="lkm_memo")  						private String lkm_memo;// '联系人备注',    						// 有一的一方的对象 PERSIST  						@ManyToOne(targetEntity=Customer.class,cascade=CascadeType.PERSIST)  						/*name:代表着外键字段的名称*/  						/*referencedColumnName:指向的主键字段的命名称*/  						@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")  						private Customer customer;    			多表对多表的注解配置:  					@Entity  					@Table(name="sys_user")  					public class User  					{  						@Id  						@Column(name="user_id")  						@GeneratedValue(strategy=GenerationType.IDENTITY)  						private Long user_id;// '用户id',  						@Column(name="user_code")  						private String user_code;// '用户账号',  						@Column(name="user_name")  						private String user_name;// '用户名称',  						@Column(name="user_password")  						private String user_password;// '用户密码',  						@Column(name="user_state")  						private String user_state;// '1:正常,0:暂停',    						// 有角色的集合  						/*targetEntity:对方的类型  						 *  						 *  						 * */  						@ManyToMany(targetEntity=Role.class,cascade=CascadeType.ALL)  						/*name: 中间表的名称  						joinColumns:自己在中间表的一些配置  						inverseJoinColumns:对方在中间表的一些配置*/  						@JoinTable(name="sys_user_role",  						joinColumns={  									/*name:自己在中间表的外键字段名称  									referencedColumnName:指向自己的主键字段名*/  							@JoinColumn(name="user_id",referencedColumnName="user_id")  						},  						inverseJoinColumns={  									/*name:对方在中间表的外键字段名称  									referencedColumnName:指向的对方的主键字段名称*/  								@JoinColumn(name="role_id",referencedColumnName="role_id")  						})  						private Set<Role> roles=new HashSet();    					@Entity  					@Table(name="sys_role")  					public class Role  					{  						@Id  						@Column(name="role_id")  						@GeneratedValue(strategy=GenerationType.IDENTITY)  						private Long role_id;// 主键id    						@Column(name="role_name")  						private String role_name;// '角色名称',  						@Column(name="role_memo")  						private String role_memo;// '备注',    						// 有用户的集合  						/*targetEntity:对方的类型  						 * mappedBy:自己在对方的属性名  						 * */  						@ManyToMany(targetEntity=User.class,mappedBy="roles")  						private Set<User> users=new HashSet();    			JPA需要在项目src下新建一个META-INF文件夹在文件夹里面配置以下信息:  				例如 :  					<?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">  							<!-- ps:当前根目录下必须得有一个持久化单元(至少要有一个数据库的连接信息配置) -->  							<persistence-unit name="aaa">  										<!-- 数据库的连接信息 -->  										<properties>  												<!-- 必选5项 -->  											<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>  											<property name="hibernate.connection.url" value="jdbc:mysql:///hibernate3"></property>  											<property name="hibernate.connection.username" value="root"></property>  											<property name="hibernate.connection.password" value="1234"></property>  											<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"></property>    												<!-- 可选的 -->  											<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"></property>  											<property name="hibernate.show_sql" value="true"></property>  											<property name="hibernate.format_sql" value="true"></property>  											<property name="hibernate.hbm2ddl.auto" value="update"></property>    										</properties>  							</persistence-unit>  					</persistence>  		JPA单表操作 :  			例如 :  				package cn.baidu.demo;    				public class Demo1  				{  					@Test //需求:保存一个客户  					public void t1()  					{  						// 加载配置文件--返回一个类似Sessionfactory的对象  						EntityManagerFactory factory = Persistence.createEntityManagerFactory("aaa");  						// 类似session  						EntityManager em = factory.createEntityManager();  						// 获取事务  						EntityTransaction tx = em.getTransaction(); // 事务未开启  						// 开启事务  						tx.begin();    						// 保存操作  						Customer ct = new Customer();  						ct.setCust_name("李冰冰");  						em.persist(ct); // 类似save()      						// 手动提交  						tx.commit();    						// 释放资源  						em.close();    					}    					@Test //查询1  					public void t2()  					{  						EntityManagerFactory factory = Persistence.createEntityManagerFactory("aaa");  						EntityManager em = factory.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 查询  						Customer ct = em.find(Customer.class, 1L); // 立即加载  类似get()  						System.out.println(ct);  						tx.commit();  						em.close();  					}    					@Test //查询2  					public void t3()  					{  						EntityManagerFactory factory = Persistence.createEntityManagerFactory("aaa");  						EntityManager em = factory.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 查询2  						Customer ct = em.getReference(Customer.class, 1L); //延迟加载  类似load()  						System.out.println(ct);  						tx.commit();  						em.close();  					}      					@Test //修改  					public void t4()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 修改  						Customer ct = em.find(Customer.class, 1L);  						ct.setCust_name("rose");  						em.merge(ct);  //类似update    						tx.commit();  						em.close();  					}    					@Test //修改 jpa支持一级缓存?  支持  					public void t5()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 修改  						Customer ct = em.find(Customer.class, 1L);  						ct.setCust_name("rose123");      						tx.commit();  						em.close();  					}      					@Test //删除  					public void t6()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						//删除  						Customer ct = em.find(Customer.class, 1L);  						em.remove(ct);  // 类似之前的delete()      						tx.commit();  						em.close();  					}      					/// jpa的批量查询方式  							// 类似咱们之前学习的query方式  							// 1 qr.getResultList();        //类似之前的 qr.list()  							// 2 hibernate对于占位符?是从0开始  jpa是从1开始  							// 3  聚合    qr.getSingleResult();  //类似之前的  qr.uniqueResult();    					@Test  					public void t7()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 全查  						Query qr = em.createQuery("from Customer");  						List<Customer> list = qr.getResultList();  //类似之前的 qr.list()  						for (Customer customer : list) {  							System.out.println(customer);  						}    						tx.commit();  						em.close();  					}      					@Test  					public void t8()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 条件  						Query qr = em.createQuery("from Customer where cust_name like ?");  						qr.setParameter(1, "b%"); // 注意:hibernate对于占位符?是从0开始  jpa是从1开始    						List<Customer> list = qr.getResultList();  						for (Customer customer : list) {  							System.out.println(customer);  						}  						tx.commit();  						em.close();  					}      					@Test  					public void t9()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 分页  						Query qr = em.createQuery("from Customer");  						qr.setFirstResult(1);  						qr.setMaxResults(3);    						List<Customer> list = qr.getResultList();  						for (Customer customer : list) {  							System.out.println(customer);  						}  						tx.commit();  						em.close();  					}      					@Test  					public void t10()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 单列  						Query qr = em.createQuery("select cust_name from Customer");  						List<Object> list = qr.getResultList();  						for (Object object : list) {  							System.out.println(object);  						}  						tx.commit();  						em.close();  					}    					@Test  					public void t11()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 多列  						Query qr = em.createQuery("select cust_id,cust_name from Customer");  						List<Object[]> list = qr.getResultList();  						for (Object[] object : list) {  							System.out.println(Arrays.toString(object));  						}  						tx.commit();  						em.close();  					}    					@Test  					public void t12()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 投影  						Query qr = em.createQuery("select new Customer(cust_id,cust_name) from Customer");  						List<Customer> list = qr.getResultList();  						for (Customer customer : list) {  							System.out.println(customer);  						}  						tx.commit();  						em.close();  					}      					@Test  					public void t13()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 排序  						Query qr = em.createQuery("from Customer order by cust_id desc");  						List<Customer> list = qr.getResultList();  						for (Customer customer : list) {  							System.out.println(customer);  						}  						tx.commit();  						em.close();  					}    					@Test  					public void t14()  					{  						EntityManager em = JPAutils.createEntityManager();  						EntityTransaction tx = em.getTransaction();  						tx.begin();    						// 聚合  						Query qr = em.createQuery("select avg(cust_id) from Customer");  						Object obj = qr.getSingleResult();  						System.out.println(obj);  						tx.commit();  						em.close();  					}  				}    		JPA一对多表的操作 :  			/*  		一对多的操作*/  		public class Demo2  		{  			@Test  // 保存一的客户3个联系人  			public void t1()  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();  				Customer ct = new Customer();  				ct.setCust_name("马总");  				LinkMan l1 = new LinkMan();  				l1.setLkm_name("大秘");  				LinkMan l2 = new LinkMan();  				l2.setLkm_name("中秘");  				LinkMan l3 = new LinkMan();  				l3.setLkm_name("小秘");    				// 双向关联  				ct.getLinkmans().add(l1);  				ct.getLinkmans().add(l2);  				ct.getLinkmans().add(l3);  				l1.setCustomer(ct);  				l2.setCustomer(ct);  				l3.setCustomer(ct);    				//保存  				em.persist(ct);  				em.persist(l1);  				em.persist(l2);  				em.persist(l3);  				tx.commit();  				em.close();  			}      			@Test  // 级联保存 (保存客户的同时把关联的联系人给保存了)  						// jpa的注解里面  @OneToMany  添加属性cascade=CascadeType.PERSIST  			public void t2()  // 根据一的一方保存多的一方的数据(掌握)  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();  				Customer ct = new Customer();  				ct.setCust_name("马总");  				LinkMan l1 = new LinkMan();  				l1.setLkm_name("大秘");  				LinkMan l2 = new LinkMan();  				l2.setLkm_name("中秘");  				LinkMan l3 = new LinkMan();  				l3.setLkm_name("小秘");    				// 双向关联  				ct.getLinkmans().add(l1);  				ct.getLinkmans().add(l2);  				ct.getLinkmans().add(l3);  				l1.setCustomer(ct);  				l2.setCustomer(ct);  				l3.setCustomer(ct);    				//保存  				em.persist(ct);  				/*em.persist(l1);  				em.persist(l2);  				em.persist(l3);*/  				tx.commit();  				em.close();  			}      			@Test  // 级联保存 (保存联系人的同时把关联的客户给保存了)  			// jpa的注解里面 @ManyToOne  添加属性cascade=CascadeType.PERSIST  			public void t3() // 根据多的一方保存一的一方的数据(不常用)  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();  				Customer ct = new Customer();  				ct.setCust_name("马总");  				LinkMan l1 = new LinkMan();  				l1.setLkm_name("大秘");  				LinkMan l2 = new LinkMan();  				l2.setLkm_name("中秘");  				LinkMan l3 = new LinkMan();  				l3.setLkm_name("小秘");    				// 双向关联  				ct.getLinkmans().add(l1);  				ct.getLinkmans().add(l2);  				ct.getLinkmans().add(l3);  				l1.setCustomer(ct);  				l2.setCustomer(ct);  				l3.setCustomer(ct);    				//保存  				/*em.persist(ct);*/  				em.persist(l1);  				em.persist(l2);  				em.persist(l3);  				tx.commit();  				em.close();  			}      			@Test  // 普通删除  			public void  t4()  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();    				Customer ct = em.find(Customer.class, 4L);  				em.remove(ct);  				tx.commit();  				em.close();  			}      			@Test  // 级联删除  			// jpa的注解里面 @OneToMany  添加属性cascade=CascadeType.REMOVE (All)  			public void  t5()  //根据一的一方删除关联的多的一方的所有数据(掌握)  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();    				Customer ct = em.find(Customer.class, 4L);  				em.remove(ct);  				tx.commit();  				em.close();  			}    		}    		JPA多表对多表的操作 :  			package cn.baidu.demo;    		import javax.persistence.CascadeType;  		import javax.persistence.EntityManager;  		import javax.persistence.EntityTransaction;  		import javax.persistence.ManyToMany;    		import org.junit.Test;    		import cn.baidu.domain.Role;  		import cn.baidu.domain.User;  		import cn.baidu.utils.JPAutils;    		/*  		多对多的操作*/  		public class Demo3  		{  			@Test  //普通保存  保存2个用户 3个角色  			public void t1()  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();    				User user1 = new User();  				user1.setUser_name("jack");  				User user2 = new User();  				user2.setUser_name("rose");    				Role r1 = new Role();  				r1.setRole_name("员工");  				Role r2 = new Role();  				r2.setRole_name("班主任");  				Role r3 = new Role();  				r3.setRole_name("助教");    				// 双向关联  				user1.getRoles().add(r1);  				user1.getRoles().add(r3);  				user2.getRoles().add(r1);  				user2.getRoles().add(r2);    				r1.getUsers().add(user1);  				r1.getUsers().add(user2);  				r2.getUsers().add(user2);  				r3.getUsers().add(user1);    				// 保存  				em.persist(user1);  				em.persist(user2);  				em.persist(r1);  				em.persist(r2);  				em.persist(r3);    				tx.commit();  				em.close();  			}    			// jpa多对多的级联操作  				// 级联保存: 保存用户的同时把关联的角色给保存了(不用)  					// @ManyToMany 添加cascade=cascade=CascadeType.PERSIST  			@Test  			public  void t2()  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();  				User user1 = new User();  				user1.setUser_name("jack");  				User user2 = new User();  				user2.setUser_name("rose");    				Role r1 = new Role();  				r1.setRole_name("员工");  				Role r2 = new Role();  				r2.setRole_name("班主任");  				Role r3 = new Role();  				r3.setRole_name("助教");    				// 双向关联  				user1.getRoles().add(r1);  				user1.getRoles().add(r3);  				user2.getRoles().add(r1);  				user2.getRoles().add(r2);    				r1.getUsers().add(user1);  				r1.getUsers().add(user2);  				r2.getUsers().add(user2);  				r3.getUsers().add(user1);    				// 保存  				em.persist(user1);  				em.persist(user2);  				/*em.persist(r1);  				em.persist(r2);  				em.persist(r3);*/    				tx.commit();  				em.close();  			}    			@Test  // 普通删除(常用)  			public void t3()  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();    				User user = em.find(User.class, 1L);  				em.remove(user);  				tx.commit();  				em.close();  			}    			@Test  // 级联删除(避免去使用)  			public void t4()  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();    				User user = em.find(User.class, 2L);  				em.remove(user);  				tx.commit();  				em.close();  			}      			// jpa的用户角色分配  					// 添加角色  					// 删除角色  					// 修改角色  			@Test  			public void t5()  			{  				EntityManager em = JPAutils.createEntityManager();  				EntityTransaction tx = em.getTransaction();  				tx.begin();  				// 获取用户  				User user = em.find(User.class, 3L);  				// 获取班主任  				Role rl = em.find(Role.class, 6L);  				//给用户添加  				user.getRoles().add(rl);  				tx.commit();  				em.close();  			}      		}    		总结:  	JPA的作用?  		给所有的orm框架提供了一套接口  	好处: 所有的ORM框架只要实现了这个JPA接口,用来操作数据库数据的方式和方法以及注解都一致了      	jpa的环境搭建: 在hibernate的环境基础上多加一个包--hibernate-entitymanager-5.0.7.Final.jar      	单表的映射  		@Entity  实体类  		@Table(name="cst_customer")  与表的映射  		@Id   指定OID属性  		@Column(name="cust_id") 指定映射的字段  		@GeneratedValue(strategy=GenerationType.IDENTITY)  指定主键的生成策略    	crud:  		persist()  			----保存    		find()  : 立即加载  		getReference():延迟加载  			-----单条数据的oid查询    		merge()  			---修改      		remove()  			---删除      	批量查询:  		  类似之前的query方式      	一对多:  		一: @OneToMany(targetEntity=LinkMan.class,mappedBy="customer")  		多: @ManyToOne(targetEntity=LinkMan.class)  			一对多的关系配置:  				@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")      	多对多:  		多(被动): @ManyToMany(targetEntity=User.class,mappedBy="roles")  		多(主动): @ManyToMany(targetEntity=Role.class)  			 多对多的关系配置:  				@JoinTable(name="中间表的名称",joinColumns="自己在中间表的配置(数组)"  				inverseJoinColumns="对方在中间表的配置(数组)")      	级联:  		cascade=CascadeType.ALL  做级联保存以及级联删除  		cascade=CascadeType.PERSIST 只做级联保存  		cascade=CascadeType.REMOVE 只做级联删除