一.JPA简介--Java Persistence API。
是SUN公司推出的一套基于ORM的规范。hibernate框架中提供了JPA的实现。JPA通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
优势:标准化/容器级特性的支持/简单方便/JPQL查询/面向对象的高级特性
二.基于JPA注解的单表映射
a.导入Hibernate必备的13个jar包;
b.创建Hibernate核心配置文件:hibernate.cfg.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <!--数据库配置 --> 8 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 9 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 10 <property name="hibernate.connection.url">jdbc:mysql:///day58</property> 11 <property name="hibernate.connection.username">root</property> 12 <property name="hibernate.connection.password">root</property> 13 <!--hibernate基本配置 --> 14 <property name="hibernate.hbm2ddl.auto">create</property> 15 <property name="hibernate.show_sql">true</property> 16 <property name="hibernate.format_sql">true</property> 17 <!--配置数据源的提供商 (记得导入c3p0的jar包) --> 18 <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> 19 <!--配置事务的隔离级别 --> 20 <property name="hibernate.connection.isolation">4</property> 21 <!--配置与当前线程绑定的session对象 --> 22 <property name="hibernate.current_session_context_class">thread</property> 23 <!--指定映射文件位置 (文件变为class,属性值为类的全限定名) --> 24 <mapping class="huguangqin.com.cnblogs.entity.Customer"/> 25 </session-factory> 26 </hibernate-configuration>
c.使用JPA注解配置实体类
1 package huguangqin.com.cnblogs.entity; 2 import java.io.Serializable; 3 import javax.persistence.Column; 4 import javax.persistence.Entity; 5 import javax.persistence.GeneratedValue; 6 import javax.persistence.GenerationType; 7 import javax.persistence.Id; 8 import javax.persistence.Table; 9 10 @Entity // 表示当前类是一个实体类 11 @Table(name = "cst_customer") // 建立当前实体类与表之间的对应关系 12 public class Customer implements Serializable { 13 @Id // 表示当前属性为主键 14 @GeneratedValue(strategy = GenerationType.IDENTITY) // 指定主键生成策略 15 @Column(name = "cust_id") // 属性对应的字段名 16 private Long custId; 17 @Column(name = "cust_name") 18 private String custName; 19 @Column(name = "cust_source") 20 private String custSource; 21 @Column(name = "cust_industry") 22 private String custIndustry; 23 @Column(name = "cust_level") 24 private String custLevel; 25 @Column(name = "cust_address") 26 private String custAddress; 27 @Column(name = "cust_phone") 28 private String custPhone; 29 30 public Long getCustId() { 31 return custId; 32 } 33 34 public void setCustId(Long custId) { 35 this.custId = custId; 36 } 37 38 public String getCustName() { 39 return custName; 40 } 41 42 public void setCustName(String custName) { 43 this.custName = custName; 44 } 45 46 public String getCustSource() { 47 return custSource; 48 } 49 50 public void setCustSource(String custSource) { 51 this.custSource = custSource; 52 } 53 54 public String getCustIndustry() { 55 return custIndustry; 56 } 57 58 public void setCustIndustry(String custIndustry) { 59 this.custIndustry = custIndustry; 60 } 61 62 public String getCustLevel() { 63 return custLevel; 64 } 65 66 public void setCustLevel(String custLevel) { 67 this.custLevel = custLevel; 68 } 69 70 public String getCustAddress() { 71 return custAddress; 72 } 73 74 public void setCustAddress(String custAddress) { 75 this.custAddress = custAddress; 76 } 77 78 public String getCustPhone() { 79 return custPhone; 80 } 81 82 public void setCustPhone(String custPhone) { 83 this.custPhone = custPhone; 84 } 85 86 // toString 87 @Override 88 public String toString() { 89 return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource 90 + ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress 91 + ", custPhone=" + custPhone + "]"; 92 } 93 94 } 95
d.实现保存功能
1 package huguangqin.com.cnblogs.demo; 2 import org.hibernate.Session; 3 import org.hibernate.Transaction; 4 import org.junit.Test; 5 import huguangqin.com.cnblogs.entity.Customer; 6 import huguangqin.com.cnblogs.util.HibernateUtils; 7 8 /** 9 * 实现保存一个客户的功能 10 */ 11 public class JPATest { 12 @Test 13 public void add() { 14 // 获取session 15 Session cs = HibernateUtils.getCurrentSession(); 16 // 开启事务 17 Transaction tx = cs.beginTransaction(); 18 // 创建对象 19 Customer c = new Customer(); 20 c.setCustName("大通股份"); 21 // 保存 22 cs.save(c); 23 // 提交 24 tx.commit(); 25 } 26 } 27
常用注解说明:
@Entity
作用:指定当前类是实体类。写上此注解用于在创建SessionFactory时,加载映射配置。
@Table
作用:指定实体类和表之间的对应关系。
属性:
name:指定数据库表的名称
@Id
作用:指定当前字段是主键。
@GeneratedValue
作用:指定主键的生成方式。
属性:
strategy :指定主键生成策略。JPA支持四种生成策略:TABLE,SEQUENCE,IDENTITY,AUTO。
IDENTITY:主键由数据库自动生成(主要是自动增长型);mysql
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。 oracle
AUTO:主键由程序控制。
TABLE:使用一个特定的数据库表格来保存主键。
@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:列的定义信息。
示例:双向一对多关系
实体类-Customer:
1 package huguangqin.com.cnblogs.entity; 2 import java.io.Serializable; 3 import java.util.HashSet; 4 import java.util.Set; 5 import javax.persistence.CascadeType; 6 import javax.persistence.Column; 7 import javax.persistence.Entity; 8 import javax.persistence.GeneratedValue; 9 import javax.persistence.GenerationType; 10 import javax.persistence.Id; 11 import javax.persistence.OneToMany; 12 import javax.persistence.Table; 13 14 @Entity // 表示当前类是一个实体类 15 @Table(name = "cst_customer") // 建立当前实体类与表之间的对应关系 16 public class Customer implements Serializable { 17 @Id // 表示当前属性为主键 18 @GeneratedValue(strategy = GenerationType.IDENTITY) // 指定主键生成策略 19 @Column(name = "cust_id") // 属性对应的字段名 20 private Long custId; 21 @Column(name = "cust_name") 22 private String custName; 23 @Column(name = "cust_source") 24 private String custSource; 25 @Column(name = "cust_industry") 26 private String custIndustry; 27 @Column(name = "cust_level") 28 private String custLevel; 29 @Column(name = "cust_address") 30 private String custAddress; 31 @Column(name = "cust_phone") 32 private String custPhone; 33 // 一对多,此处为关键处,mappedBy-放弃外键维护权 34 @OneToMany(targetEntity = Linkman.class, mappedBy = "customer", cascade = CascadeType.ALL) 35 private Set<Linkman> linkmans = new HashSet<>(); 36 37 public Set<Linkman> getLinkmans() { 38 return linkmans; 39 } 40 41 public void setLinkmans(Set<Linkman> linkmans) { 42 this.linkmans = linkmans; 43 } 44 45 public Long getCustId() { 46 return custId; 47 } 48 49 public void setCustId(Long custId) { 50 this.custId = custId; 51 } 52 53 public String getCustName() { 54 return custName; 55 } 56 57 public void setCustName(String custName) { 58 this.custName = custName; 59 } 60 61 public String getCustSource() { 62 return custSource; 63 } 64 65 public void setCustSource(String custSource) { 66 this.custSource = custSource; 67 } 68 69 public String getCustIndustry() { 70 return custIndustry; 71 } 72 73 public void setCustIndustry(String custIndustry) { 74 this.custIndustry = custIndustry; 75 } 76 77 public String getCustLevel() { 78 return custLevel; 79 } 80 81 public void setCustLevel(String custLevel) { 82 this.custLevel = custLevel; 83 } 84 85 public String getCustAddress() { 86 return custAddress; 87 } 88 89 public void setCustAddress(String custAddress) { 90 this.custAddress = custAddress; 91 } 92 93 public String getCustPhone() { 94 return custPhone; 95 } 96 97 public void setCustPhone(String custPhone) { 98 this.custPhone = custPhone; 99 } 100 101 // toString 102 @Override 103 public String toString() { 104 return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource 105 + ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress 106 + ", custPhone=" + custPhone + "]"; 107 } 108 109 } 110
实体类-Linkman
1 package huguangqin.com.cnblogs.entity; 2 import java.io.Serializable; 3 import javax.persistence.Column; 4 import javax.persistence.Entity; 5 import javax.persistence.GeneratedValue; 6 import javax.persistence.GenerationType; 7 import javax.persistence.Id; 8 import javax.persistence.JoinColumn; 9 import javax.persistence.ManyToOne; 10 import javax.persistence.Table; 11 12 @Entity 13 @Table(name = "cst_linkman") 14 public class Linkman implements Serializable { 15 @Id 16 @GeneratedValue(strategy = GenerationType.IDENTITY) 17 @Column(name = "lkm_id") 18 private Long lkmId;// 联系人编号(主键) 19 @Column(name = "lkm_name") 20 private String lkmName;// 姓名 21 @Column(name = "lkm_gender") 22 private String lkmGender;// 性别 23 @Column(name = "lkm_phone") 24 private String lkmPhone;// 办 公电话 25 @Column(name = "lkm_mobile") 26 private String lkmMobile;// 手机 27 @Column(name = "lkm_email") 28 private String lkmEmail;// 邮箱 29 @Column(name = "lkm_position") 30 private String lkmPosition;// 职位 31 @Column(name = "lkm_memo") 32 private String lkmMemo;// 备注 33 // 多个linkman对应一个customer,此处为关键 34 @ManyToOne(targetEntity = Customer.class) 35 @JoinColumn(name = "lkm_cust_id", referencedColumnName = "cust_id") // 指定外键名和参照主键 36 private Customer customer; 37 38 public Customer getCustomer() { 39 return customer; 40 } 41 42 public void setCustomer(Customer customer) { 43 this.customer = customer; 44 } 45 46 // getter/setter 47 public Long getLkmId() { 48 return lkmId; 49 } 50 51 public void setLkmId(Long lkmId) { 52 this.lkmId = lkmId; 53 } 54 55 public String getLkmName() { 56 return lkmName; 57 } 58 59 public void setLkmName(String lkmName) { 60 this.lkmName = lkmName; 61 } 62 63 public String getLkmGender() { 64 return lkmGender; 65 } 66 67 public void setLkmGender(String lkmGender) { 68 this.lkmGender = lkmGender; 69 } 70 71 public String getLkmPhone() { 72 return lkmPhone; 73 } 74 75 public void setLkmPhone(String lkmPhone) { 76 this.lkmPhone = lkmPhone; 77 } 78 79 public String getLkmMobile() { 80 return lkmMobile; 81 } 82 83 public void setLkmMobile(String lkmMobile) { 84 this.lkmMobile = lkmMobile; 85 } 86 87 public String getLkmEmail() { 88 return lkmEmail; 89 } 90 91 public void setLkmEmail(String lkmEmail) { 92 this.lkmEmail = lkmEmail; 93 } 94 95 public String getLkmPosition() { 96 return lkmPosition; 97 } 98 99 public void setLkmPosition(String lkmPosition) { 100 this.lkmPosition = lkmPosition; 101 } 102 103 public String getLkmMemo() { 104 return lkmMemo; 105 } 106 107 public void setLkmMemo(String lkmMemo) { 108 this.lkmMemo = lkmMemo; 109 } 110 111 // toString 112 @Override 113 public String toString() { 114 return "Linkman [lkmId=" + lkmId + ", lkmName=" + lkmName + ", lkmGender=" + lkmGender + ", lkmPhone=" 115 + lkmPhone + ", lkmMobile=" + lkmMobile + ", lkmEmail=" + lkmEmail + ", lkmPosition=" + lkmPosition 116 + ", lkmMemo=" + lkmMemo + "]"; 117 } 118 119 } 120
测试代码:
1 package huguangqin.com.cnblogs.demo; 2 3 import org.hibernate.Session; 4 import org.hibernate.Transaction; 5 import org.junit.Test; 6 7 import huguangqin.com.cnblogs.entity.Customer; 8 import huguangqin.com.cnblogs.entity.Linkman; 9 import huguangqin.com.cnblogs.util.HibernateUtils; 10 11 /** 12 * 一对多,保存一个客户,即能保存对应的多个联系人 13 */ 14 public class JPATest01 { 15 @Test 16 public void add() { 17 // 获取session 18 Session cs = HibernateUtils.getCurrentSession(); 19 // 开启事务,并返回事务对象 20 Transaction tx = cs.beginTransaction(); 21 // 创建对象 22 Customer c = new Customer(); 23 c.setCustName("百度"); 24 Linkman man = new Linkman(); 25 man.setLkmName("大王"); 26 // 创建关系--双方均需创建关系,否则外键添加不上 27 c.getLinkmans().add(man); 28 man.setCustomer(c); 29 // 保存 30 cs.save(c); 31 // 提交事务 32 tx.commit(); 33 } 34 } 35
四.多对多关系映射
注解说明
@ManyToMany
作用:用于映射多对多关系
属性:
cascade:配置级联操作。
fetch:配置是否采用延迟加载。
targetEntity:配置目标的实体类。映射多对多的时候不用写。
@JoinTable
作用:针对中间表的配置
属性:
nam:配置中间表的名称
joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段
inverseJoinColumn:中间表的外键字段关联对方表的主键字段
@JoinColumn
作用:用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一
nullable:是否允许为空。默认值允许。
insertable:是否允许插入。默认值允许。
updatable:是否允许更新。默认值允许。
columnDefinition:列的定义信息。
示例:多对多关系
实体类:-User
1 package huguangqin.com.cnblogs.entity; 2 import java.io.Serializable; 3 import java.util.HashSet; 4 import java.util.Set; 5 import javax.persistence.CascadeType; 6 import javax.persistence.Column; 7 import javax.persistence.Entity; 8 import javax.persistence.GeneratedValue; 9 import javax.persistence.GenerationType; 10 import javax.persistence.Id; 11 import javax.persistence.JoinColumn; 12 import javax.persistence.JoinTable; 13 import javax.persistence.ManyToMany; 14 import javax.persistence.Table; 15 16 @Entity 17 @Table(name = "user") 18 public class User implements Serializable { 19 20 @Id 21 @GeneratedValue(strategy = GenerationType.IDENTITY) 22 @Column(name = "user_id") 23 private Long userId; 24 25 @Column(name = "user_name") 26 private String userName; 27 28 @Column 29 private String address; 30 31 // 对应多个角色 32 @ManyToMany(targetEntity = Role.class, cascade = CascadeType.ALL) 33 @JoinTable(name = "role_user", 34 joinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id") }, 35 inverseJoinColumns = {@JoinColumn(name = "sys_role_id", referencedColumnName = "role_id") }) 36 private Set<Role> roles = new HashSet<>(0); 37 38 // getter/setter 39 public Long getUserId() { 40 return userId; 41 } 42 43 public void setUserId(Long userId) { 44 this.userId = userId; 45 } 46 47 public String getUserName() { 48 return userName; 49 } 50 51 public void setUserName(String userName) { 52 this.userName = userName; 53 } 54 55 public String getAddress() { 56 return address; 57 } 58 59 public void setAddress(String address) { 60 this.address = address; 61 } 62 63 public Set<Role> getRoles() { 64 return roles; 65 } 66 67 public void setRoles(Set<Role> roles) { 68 this.roles = roles; 69 } 70 71 // toString 72 @Override 73 public String toString() { 74 return "User [userId=" + userId + ", userName=" + userName + ", address=" + address + ", roles=" + roles + "]"; 75 } 76 77 } 78
实体类:Role
1 package huguangqin.com.cnblogs.entity; 2 import java.io.Serializable; 3 import java.util.HashSet; 4 import java.util.Set; 5 import javax.persistence.Column; 6 import javax.persistence.Entity; 7 import javax.persistence.GeneratedValue; 8 import javax.persistence.GenerationType; 9 import javax.persistence.Id; 10 import javax.persistence.ManyToMany; 11 import javax.persistence.Table; 12 13 @Entity 14 @Table(name = "role") 15 public class Role implements Serializable { 16 17 @Id 18 @GeneratedValue(strategy = GenerationType.IDENTITY) 19 @Column(name = "role_id") 20 private Long roleId; 21 22 @Column(name = "role_name") 23 private String roleName; 24 25 // 对应多个用户 26 @ManyToMany(mappedBy = "roles") // 放弃维护权,已由对方Role属性维护 27 private Set<User> users = new HashSet<>(0); 28 29 // getter/setter 30 public Long getRoleId() { 31 return roleId; 32 } 33 34 public void setRoleId(Long roleId) { 35 this.roleId = roleId; 36 } 37 38 public String getRoleName() { 39 return roleName; 40 } 41 42 public void setRoleName(String roleName) { 43 this.roleName = roleName; 44 } 45 46 public Set<User> getUsers() { 47 return users; 48 } 49 50 public void setUsers(Set<User> users) { 51 this.users = users; 52 } 53 54 // toString 55 @Override 56 public String toString() { 57 return "Role [roleId=" + roleId + ", roleName=" + roleName + ", users=" + users + "]"; 58 } 59 60 } 61 62 测试代码: 63 package huguangqin.com.cnblogs.demo; 64 import org.hibernate.Session; 65 import org.hibernate.Transaction; 66 import org.junit.Test; 67 import huguangqin.com.cnblogs.entity.Role; 68 import huguangqin.com.cnblogs.entity.User; 69 import huguangqin.com.cnblogs.util.HibernateUtils; 70 71 public class AnotationTest { 72 @Test 73 public void test() { 74 // 获取Session 75 Session cs = HibernateUtils.getCurrentSession(); 76 // 开启事务 77 Transaction tx = cs.beginTransaction(); 78 // 构建对象 79 Role r = new Role(); 80 r.setRoleName("model"); 81 User u = new User(); 82 u.setUserName("Rose"); 83 // 创建关系 84 r.getUsers().add(u); 85 u.getRoles().add(r); 86 // 保存,由于设置了级联操作,只保存一个即可 87 cs.save(u); 88 // 提交事务 89 tx.commit(); 90 } 91 92 } 93