hibernate注解JPA
1.JPA与hibernate
什么是JPA ?
java persistence api :java持久化api,同一的ORM规范,是由sun公司指定的规范接口,hibernate实现了JPA规范。
我们可以使用javax.persistence下的注解,配置实体类,使用hibernate的session操作。在hibernate.cfg.xml中配置映射文件:
<mapping class="">
2. 如何搭建JPA环境
2.1 导入jar包
(1)required
(2)mysql数据库驱动
(3)JPA
2.2 配置文件
(1)在src目录下创建META-INF目录(java项目),在该目录下创建persistence.xml主配置文件,
xsd约束在下面的目录下找:
(2)配置持久化单元<persistence-unit>
<?xml version="1.0" encoding="UTF-8"?> <!-- 主配置文件,名称必须为persistence.xml 放在META-INF下 --> <!-- 导入xsd约束 --> <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"> <!-- persistence-unit:用于配置持久化单元,可以配置多个 属性:name:指定持久化单元名称 如果配置多个,名称不能重复 transaction-type:用于指定事务类型 可选值: RESOURCE_LOCAL:本地事务类型(我们一般用这个) JTA:一般是在集群情况下使用(我们不管) --> <persistence-unit name="myJPAUnit" transaction-type="RESOURCE_LOCAL"> <!-- 用于配置指定JPA规范的提供商 可以不配置 --> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <!-- 用于指定使用JPA注解的实体类位置 可以不配置--> <class>cn.getword.domain.User</class> <class>cn.getword.domain.Student</class> <class>cn.getword.domain.Clazz</class> <!-- 主要配置 都来源于我们之间的 hibernate.cfg.xml文件中的配置 --> <properties> <!-- 第一部分:连接数据库的信息 可以从源码包的project 的etc下的hibernate.properties文件中找到--> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/db_hibernate2?characterEncoding=utf-8"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value="123"/> <!-- 配置数据库方言 --> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <!-- 第二部分:hibernate配置的可选项 可以从源码包的project 的etc下的hibernate.properties文件中找到--> <!-- 配置是否在控制台输出sql语句 --> <property name="hibernate.show_sql" value="true"/> <!-- 配置是否以格式化的方式输出sql语句 --> <property name="hibernate.format_sql" value="false"/> <!-- 配置DDL执行方式: 可选值: update:在运行的时候,判断实体类结构与表结构是否一致,如果不一致,就更新表结构 如果表不存在,则创建 --> <property name="hibernate.hbm2ddl.auto" value="update"/> <!-- 配置连接池的提供商 为c3p0--> <!-- <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"/> --> </properties> </persistence-unit> </persistence>
(3)JPAUtil:获取数据库操作对象
package cn.getword.utils; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class JPAUtil { private static EntityManagerFactory factory; //对EntityManagerFactory进行初始化 static { //参数是我们主配置文件中的持久化单元名称 factory = Persistence.createEntityManagerFactory("myJPAUnit"); } //提供获取EntityManager的方法 public static EntityManager createEntityManager() { return factory.createEntityManager(); } public static void main(String[] args) { createEntityManager(); } }
2.3 实体类注解
由于hibernate遵循JPA规则,因此所有注解类都在javax.persistence包下。
@Entity @Table(name = "tb_user") public class User implements Serializable { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "username") private String username; @Column(name = "age") private Integer age; @Column(name = "deleted") private Integer deleted; //get和set方法省略 }
@Entity():用于声明该类是一个实体类, 名称和HQL的实体类名对应
@Table()
@Id:主键字段
@Column():指定该属性在表中对应的字段名
@Column(nullable=false,columnDefinition=”INT default 0”)
用注解设置属性的默认值时
- 默认值
- unique索引
@GeneratedValue(strategy="") :主键生成策略
(1)一对多
package cn.getword.domain; import javax.persistence.*; import java.io.Serializable; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "tb_clazz") public class Clazz implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column private String className; //实例化,可以防止空指针异常 //targetEntity:目标对象 // mappedBy:维护关系反转,值为对方实体类中定义的当前类的属性名【也就是Student类中定义的Clazz属性名】 //cascade:级联操作 // 默认是lazy加载 @OneToMany(targetEntity = Student.class, mappedBy = "clazz2", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) private Set<Student> students = new HashSet<>(0); //长度设为0 public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } @Override public String toString() { return "Clazz{" + "id=" + id + ", className='" + className + '\'' + '}'; } }
package cn.getword.domain; import javax.persistence.*; import javax.print.attribute.standard.MediaSize; import java.io.Serializable; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "tb_student") public class Student implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column private String stuName; @Column private Integer age; // 目标类 级联操作 @ManyToOne(targetEntity = Clazz.class, cascade = {CascadeType.ALL}) // 外键关系 外键名称 依赖表的主键名称 @JoinColumn(name = "clazz_id", referencedColumnName = "id") private Clazz clazz2; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Clazz getClazz2() { return clazz2; } public void setClazz2(Clazz clazz2) { this.clazz2 = clazz2; } @Override public String toString() { return "Student{" + "id=" + id + ", stuName='" + stuName + '\'' + ", age=" + age + '}'; } }
Clazz:一的一方
@OneToMany(targetEntity = , mappedBy="")
mappedBy:维护关系权利反转
第一:mappedBy这个注解只能够用在@OntToOne,@OneToMany,@manyToMany中,不能够用在@manyToOne中;
第二,这个注解看网上的意思可以简单地理解为:这个注解用在主表的一方,就是被引用的一方;
第三,这个注解是与@JoinColumn这个注解是互斥的,因为@JoinColumn这个注解使用在拥有外键的表的一方,就是从表的一方。
第四,这个注解的属性值是:指向另外一个类中定义的一个属性。这里指的是Student类中定义的Clazz属性名(clazz2)。
student:多的一方
@ManyToOne(targetEntity=)
@JoinColumn(name="", referenceColumnName="") 外键名称,依赖表id名称
(2)多对多
package cn.getword.domain; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.io.Serializable; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "tb_student") public class Student implements Serializable { @Id @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid",strategy = "uuid") @Column(name = "s_id", length = 32) private String sid; @Column private String stuName; @Column private Integer age; // 目标类 级联操作 @ManyToOne(targetEntity = Clazz.class, cascade = {CascadeType.ALL}) // 外键关系 外键名称 依赖表的主键名称 @JoinColumn(name = "clazz_id", referencedColumnName = "cid") private Clazz clazz2; @ManyToMany @JoinTable(name = "tb_teacher_student", joinColumns = { @JoinColumn(name = "sid", referencedColumnName = "s_id"), // 当前实体类对应的表中的字段【主键】提供给中间表作为外键 }, inverseJoinColumns = { @JoinColumn(name = "tid", referencedColumnName = "t_id")// 对方放弃权利的实体类对应的表中的字段【主键】提供给中间表作为外键 }) private Set<Teacher> teachers = new HashSet<>(0); public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Clazz getClazz2() { return clazz2; } public void setClazz2(Clazz clazz2) { this.clazz2 = clazz2; } public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } @Override public String toString() { return "Student{" + "id=" + sid + ", stuName='" + stuName + '\'' + ", age=" + age + '}'; } }
package cn.getword.domain; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.io.Serializable; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "tb_teacher") public class Teacher implements Serializable { @Id @GeneratedValue(generator = "uuid") // 使用名为uuid的生成器 @GenericGenerator(name = "uuid", strategy = "uuid") // 声明一个名为uuid的生成器,生成策略为uuid @Column(name = "t_id", length = 32) private String tid; @Column private String name; @ManyToMany(mappedBy = "teachers") private Set<Student> students = new HashSet<Student>(0); public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Teacher:放弃维护关系
@ManyToMany(mappedBy="teachers") 必须有一方放弃维护关系的权利
Student:维护关系
@ManyToMany(cascade = )
@JoinTable():
@JoinTable(name = "tb_teacher_student", joinColumns = {
@JoinColumn(name = "sid", referencedColumnName = "s_id"), // 当前实体类对应的表中的字段【主键】提供给中间表作为外键
}, inverseJoinColumns = {
@JoinColumn(name = "tid", referencedColumnName = "t_id")// 对方放弃权利的实体类对应的表中的字段【主键】提供给中间表作为外键
})
uuid错误:
原因:字段长度太大,mysql容不下,需要把编码设为utf8,把主键长度设为固定长度
2.4 JPA工具类
package cn.getword.utils; import org.junit.Test; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class JPAUtil { private static EntityManagerFactory factory; //对EntityManagerFactory进行初始化 static { //参数是我们主配置文件中的持久化单元名称 factory = Persistence.createEntityManagerFactory("myJPAUnit"); } //提供获取EntityManager的方法 public static EntityManager createEntityManager() { return factory.createEntityManager(); } @Test public void test() { EntityManager entityManager = JPAUtil.createEntityManager(); } }
2.5 操作
一般不使用JPA操作,仅仅使用JPA的注解,对于数据库操作还是使用hibernate提供的session。
3. JPA配置和hibernate操作结合
使用JPA的注解、hibernate的操作。day31/hibernate_jpa3
3.1 实体类
和JPA一样
3.2 配置文件
还是hibernate主配置文件:hibernate.cfg.xml
需要修改的是:<mapping class="" />
3.3 数据库操作不变
end