微微撒 2020-03-08
JPA是Java Persistence API的简称,它是Sun公司在充分吸收现有ORM框架(Hibernate)的基础上,开发而来的一个Java EE 5.0平台标准的开源的对象关系映射(ORM)规范。
Hibernate与JPA的关系:
Hibernate是一个开放源代码的对象关系映射(ORM)框架,它对JDBC进行了非常轻量级的对象封装,将POJO与数据库表建立映射关系,是一个全自动的ORM框架,Hibernate可以自动生成SQL语句,自动执行,使Java程序员可以随心所欲地使用面向对象思维来操纵数据库。
而JPA是Sun官方提出的Java持久化规范,而JPA是在充分吸收Hibernate、TopLink等ORM框架的基础上发展而来的。
总结一句话就是:JPA是持久化的关系映射规范、接口API,而Hibernate是其实现。
优点:
① 操作代码很简单,插入—persist、修改—merge、查询—find、删除—remove;
② 直接面向持久化对象操作;
③ 提供了世界级的数据缓存:包括一级缓存、二级缓存、查询缓存;
④ 切换数据库移植性强,对应各种数据库抽取了一个方言配置接口,换数据库只需修改方言配置、驱动jar包、数据库连接4个信息即可。
缺点:
① 不能干预SQL语句的生成;
② 对于SQL优化效率要求较高的项目,不适合使用JPA;
③ 对于数据量上亿级别的大型项目,也不适合使用JPA。
Hibernate版本可以到官网进行下载:http://hibernate.org/orm/releases/
这里作为学习使用Hibernate 4.3.8的版本jar包,即JPA2.1版本为例进行项目jar包的构建:
导入项目所需要的Hibernate的jar包分为三类:
① Hibernate所必需的jar包:
目录路径位置:\hibernate-release-4.3.8.Final\lib\required
导入如下图所示jar包集合:
② 还需要导入JPA支持的jar包,目录路径:\hibernate-release-4.3.8.Final\lib\jpa与数据库Mysql连接驱动jar包;
配置文件必需放在项目的classpath目录的资源文件resources\META-INF目录下(JPA规范要求);
persistence.xml文件具体配置如下:
<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:和项目名称对应--> <persistence-unit name="cn.yif.jpa01" transaction-type="RESOURCE_LOCAL"> <properties> <!-- 必须配置4个连接数据库属性:配置信息可以在project/etc/hibernate.properties中找到 --> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.url" value="jdbc:mysql:///jpa01_0307" /> <property name="hibernate.connection.username" value="root" /> <property name="hibernate.connection.password" value="admin" /> <!-- 必须配置1个数据库方言属性 --> <!-- 实现跨数据库关键类 :查询MySQLDialect的getLimitString方法 --> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <!-- 可选配置 --> <!-- 是否自动生成表 --> <property name="hibernate.hbm2ddl.auto" value="create" /> <!-- 是否显示sql --> <property name="hibernate.show_sql" value="true" /> <!-- 格式化sql --> <property name="hibernate.format_sql" value="true" /> </properties> </persistence-unit> </persistence>
package cn.yif.domain; import javax.persistence.*; //@Entity表示该类是由jpa管理的持久化对象,对应数据库中的一张表 @Entity //@Table表示对应数据库的表名 @Table(name = "t_employee") public class Employee { //@Id是必须的注解,表示对应数据库的主键 @Id //@GeneratedValue表示主键的生成策略,多数都是使用AUTO //@GeneratedValue默认不配置也是AUTO @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; //@Column表示如果数据库列名与属性名不一致,需要配置 @Column(name = "e_name") private String name; @Column(name = "e_age") private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Employee{" + "id=" + id + ", name=‘" + name + ‘\‘‘ + ", age=" + age + ‘}‘; } }
import cn.yif.domain.Employee; import org.junit.Test; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class JPAHelloTest { @Test public void testInsertEmpByJPA(){ Employee employee = new Employee(); employee.setName("高伟翔"); employee.setAge(34); // 对应配置文件里面的persistence-unit name="cn.yif.jpa01" // 通过持久化类创建一个实体类管理工厂 EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("cn.yif.jpa01"); //创建一个实体管理类,可以实现CRUD EntityManager entityManager = entityManagerFactory.createEntityManager(); //由entityManager来开启事务 EntityTransaction transaction = entityManager.getTransaction(); transaction.begin(); //持久操作CRUD 写入persist entityManager.persist(employee); // 提交事务 transaction.commit(); //关闭资源 entityManager.close(); entityManagerFactory.close(); } }
通过以上的步骤,就可以在创建的jpa01_0307数据库里面由JPA自动创建一张t_employee表并插入一条数据:
package cn.yif.utils; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; /** * 工具类:单例模式/静态单例模式 静态方法 */ public class JPAUtil { // 私有化这个构造器,不让其它人创建这个类 private JPAUtil(){} // 实体管理工厂 // 注意:EntityManagerFactory这个类是线程安全 private static EntityManagerFactory entityManagerFactory; /** * 静态代码块,类加载的时候就会执行里面的代码,只会执行一次 */ static{ try { entityManagerFactory = Persistence.createEntityManagerFactory("cn.yif.jpa01"); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("拿到EntityManagerFactory运行时出错:"+e.getMessage()); } } // 拿到一个EntityManager对象 // 每次拿EntityManager都需要重新创建(EntityManager不是线程安全的对象,每次使用都重新创建一次) public static EntityManager getEntityManager(){ return entityManagerFactory.createEntityManager(); } public static void close(EntityManager entityManager){ //关闭资源 entityManager.close(); entityManagerFactory.close(); } }
如上,hibernate.hbm2ddl.auto属性的value值一共有4种配置:create-drop、create、update、validate。下面来解释这四种不同配置场景的区别与作用:
① create-drop
create-drop作用:先删除表,在创建表,最后再删除表;
注意:必须执行entityManagerFactory.close()代码才会最后删除表,执行drop表功能
② create
create作用:先删除表,在创建表。
③ update
update作用:
如果数据库中没有当前JPA持久化的表就根据最新映射来创建表;
如果数据库已经有表了,则不会删除原来表的任何结构,只会新增列;
注意如果是表里面没有这个属性,映射信息domain类中有,则会增加这个属性
④ validate
validate作用:
如果数据库中表不存在或者domain类中的属性大于数据库表中的字段,会抛出异常;
会验证映射信息domain类与数据库表中的对应字段,如果一一对应或者映射小于数据库表中的字段,不会抛出异常
① 日期与时间格式配置
使用@Temporal注解配置:
@Temporal(TemporalType.TIMESTAMP)
默认配置,会设置数据库表的时间格式为:“yyyy-MM-dd hh:mm:ss"
@Temporal(TemporalType.DATE)
会设置数据库表的时间格式为:”yyyy-MM-dd"
@Temporal(TemporalType.TIME)
会设置数据库表的时间格式为:“hh:mm:ss”
持久类domain配置
@Temporal(TemporalType.TIMESTAMP) private Date createTime; // 创建时间:格式--"yyyy-MM-dd hh:mm:ss"(年--月--日--时--分--秒) @Temporal(TemporalType.DATE) private Date brithday; // 生日:格式--"yyyy-MM-dd"(年--月--日) @Temporal(TemporalType.TIME) private Date classTime; // 上课时间:格式--"hh:mm:ss""(时--分--秒)
具体设置格式如下:
domain类对应普通表中的长度如果不配置长度,默认vachar字段类型在数据库表中的长度会给到255,比较占用空间,我们可以通过JPA注解配置来指定固定的length长度值。
普通String类属性字段长度配置:
@Column(name = "t_name", length = 20)
@Column(name = "pwd", length = 100)
在@Column注解上加上length长度配置,即可指定数据库表中varchar字段的长度;
长文本类型属性字段配置:
在对应domain类的属性上加上注解@Lob,对应这个字段在数据库中就会被设置成longtext类型,能储存大文本。
持久类domain配置
@Lob // 设置为长文本类型 private String Intro; // 个人简介:长文本类型
非空约束:
配置@Column(nullable = false)
唯一约束:
配置@Column(unique = true)
① 临时属性配置:Transient(临时属性—该属性在持久化对象上有,但是不会写入数据库);
@Transient private String temp;
② 设置是否能更新able:@Column(updatable=false),表示添加的时候会进行添加,但是修改的时候不能修改(了解就行,一般不用);
③ 设置是否能添加able:@Column(insertable=false),表示添加的时候不能操作,但是修改的时候可以操作修改(了解就行,一般不用);
④ 自定义持久类domain属性规则:@Column(columnDefinition=”int check(age > 18)”),Mysql不支持这个规则,Oracle才支持(了解就行,Mysql数据库用不了)
是一个替代hibernate的一个作用于数据库的框架。 这里整合后不需要写一些简单的sql语句。 2、在resources下创建templates文件夹,在其下就可以书写页面了,和HTML的风格相似。