【java框架】JPA(1) -- JPA入门

2020-03-08 16:04:21来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

【java框架】JPA(1) -- JPA入门

1.   JPA认识

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是其实现。

1.1.  JPA的优缺点

优点:

①    操作代码很简单,插入—persist、修改—merge、查询—find、删除—remove;

②    直接面向持久化对象操作;

③    提供了世界级的数据缓存:包括一级缓存、二级缓存、查询缓存;

④    切换数据库移植性强,对应各种数据库抽取了一个方言配置接口,换数据库只需修改方言配置、驱动jar包、数据库连接4个信息即可。

缺点:

①    不能干预SQL语句的生成;

②    对于SQL优化效率要求较高的项目,不适合使用JPA;

③    对于数据量上亿级别的大型项目,也不适合使用JPA。

2.   手动创建一个Hello World的JPA项目

2.1.  导入JPA项目所需jar包

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包;

2.2.  配置核心配置文件persistence.xml

配置文件必需放在项目的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>

2.3.创建持久化Domain类Employee

 

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 +
                '}';
    }
}

2.4.创建Junit4测试类代码

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表并插入一条数据:

 

 

3.   实现完整的JPA CRUD流程

3.1.抽取JPAUtil类

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();
    }
}

4.   persitence.xml中hibernate.hbm2ddl.auto属性值配置

如上,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类与数据库表中的对应字段,如果一一对应或者映射小于数据库表中的字段,不会抛出异常

5.   单表映射配置细节

5.1.持久类domain映射配置细节

5.1.1.     日期与时间类型格式

①    日期与时间格式配置

使用@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""(时--分--秒)

具体设置格式如下:

 

 

5.1.2.     文本长度与长文本类型

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; // 个人简介:长文本类型

 

 

5.1.3.     属性约束设置

非空约束:

配置@Column(nullable = false)

 

唯一约束:

配置@Column(unique = true)

 

 

 

5.1.4.     其他映射配置

①    临时属性配置:Transient(临时属性—该属性在持久化对象上有,但是不会写入数据库);

@Transient
private String temp;

②   设置是否能更新able:@Column(updatable=false),表示添加的时候会进行添加,但是修改的时候不能修改(了解就行,一般不用);

③    设置是否能添加able:@Column(insertable=false),表示添加的时候不能操作,但是修改的时候可以操作修改(了解就行,一般不用);

④    自定义持久类domain属性规则:@Column(columnDefinition=”int check(age > 18)”),Mysql不支持这个规则,Oracle才支持(了解就行,Mysql数据库用不了)

 


原文链接:https://www.cnblogs.com/yif0118/p/12442116.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Java基础篇(01):基本数据类型,核心点整理

下一篇:java面对对象入门(8)-接口vs抽象类区别