JPA-Hibernate

 一. JPA与hibernate的关系

JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现。

 JPA和Hibernate的关系就像JDBC和数据库JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。

二 . JPA-hibernate入门案例

1.  需求介绍:实现的功能是保存一个客户到数据库的客户表中

2. 导入maven依赖:

    <properties>
        <!--hibernate版本-->
        <project.hibernate.version>5.0.7.Final</project.hibernate.version>
    </properties>

    <dependencies>
        <!-- hibernate对jpa的支持包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${project.hibernate.version}</version>
        </dependency>

        <!-- c3p0 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${project.hibernate.version}</version>
        </dependency>

        <!--mysql-JDBC驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    </dependencies>

3. 创建客户的实体类、编写实体类和数据库表的映射配置:

/**
*     所有的注解都是使用JPA的规范提供的注解,
*	  所以在导入注解包的时候,一定要导入javax.persistence下的注解包
*/
@Entity //声明实体类
@Data   //lombok注解
@Table(name = "cst_customer") //建立实体类和表的映射关系
public class Customer implements Serializable {
    @Id //声明当前私有属性为主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) //配置主键的生成策略
    @Column(name = "cust_id",columnDefinition = "bigint(32) NOT NULL COMMENT '客户编号(主键)'")
    private Long custId;

    @Column(name = "cust_name",columnDefinition = "varchar(32) NOT NULL COMMENT '客户名称(公司名称)'")
    private String custName;

    @Column(name = "cust_source",columnDefinition = "varchar(32) DEFAULT NULL COMMENT '客户信息来源'")
    private String custSource;

    @Column(name="cust_industry",columnDefinition = "varchar(32) DEFAULT NULL COMMENT '客户所属行业'")
    private String custIndustry;

    @Column(name = "cust_level",columnDefinition = "varchar(32) DEFAULT NULL COMMENT '客户级别'")
    private String custLevel;

    @Column(name = "cust_address",columnDefinition = "varchar(32) DEFAULT NULL COMMENT '客户联系地址'")
    private String custAddress;

    @Column(name="cust_phone",columnDefinition = "varchar(32) DEFAULT NULL COMMENT '客户联系电话'")
    private String custPhone;
}

JPA常用注解的说明: 

@Entity

         作用:指定当前类是实体类。

@Table

         作用:指定实体类和表之间的对应关系。

         属性:name:指定数据库表的名称

@Id

         作用:指定当前字段是主键。

@GeneratedValue

         作用:指定主键的生成方式。

         属性:strategy :指定主键生成策略。

JPA提供四种主键生成策略:

①GenerationType.IDENTITY:主键由数据库自动生成,条件是数据库支持自增(mysql)。

②GenerationType.SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列(oracle)。

③GenerationType.AUTO:主键由程序控制(适合两种及以上数据库同时使用)

④GenerationType.TABLE:使用一个特定的数据库表格来保存主键

@Column

         作用:指定实体类属性和数据库表之间的对应关系

         属性:

         name:指定数据库表的列名称。

         unique:是否唯一  

         nullable:是否可以为空  

         inserttable:是否可以插入  

         updateable:是否可以更新  

         columnDefinition: 定义建表时创建此列的DDL(注意:使用这个属性必须设置数据类型)

         secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字搭建开发环境[重点]

 4. 配置JPA核心配置文件-persistence.xml

在java工程的src路径下创建一个名为META-INF的文件夹,在此文件夹下创建一个名为persistence.xml的配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <!--配置持久化单元
    name:持久化单元名称
    transaction-type:事务类型
        RESOURCE_LOCAL:本地事务管理,只能针对一种数据库,不支持分布式的数据库
        JTA:分布式事务管理,可以支持分布式的数据库
    -->
    <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
        <!--配置JPA规范的服务提供商 -->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <!-- 配置数据源 -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="admin123"/>
            <!--jpa提供者的可选配置:我们的JPA规范的提供者为hibernate,所以jpa的核心配置中兼容hibernate的配置 -->
            <!--显示sql语句-->
            <property name="hibernate.show_sql" value="true"/>
            <!--格式化sql语句-->
            <property name="hibernate.format_sql" value="true" />
            <!--自动创建|更新|验证数据库表结构
            create:每次加载hibernate时都会删除上一次的生成的表,然后再重新来生成新表
            update:运行时创建表(若原始有表存在,不会删除表,直接进行数据更新)
            -->
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>

</persistence>

 5.  实现保存操作

    @Test
    public void testSave() {
        EntityManagerFactory entityManagerFactory = null;
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            //获得实体管理器工厂
            entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
            //获得实体管理器
            entityManager = entityManagerFactory.createEntityManager();
            //获得实体事务
            transaction = entityManager.getTransaction();
            transaction.begin();
            Customer customer = new Customer();
            customer.setCustName("阿里巴巴");
            customer.setCustIndustry("互联网");
            entityManager.persist(customer);
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
            entityManagerFactory.close();
        }
    }

三.JPA的API介绍

1. Persistence对象

Persistence对象主要作用是用于获取EntityManagerFactory对象的 。通过调用该类的createEntityManagerFactory静态方法,根据配置文件中持久化单元名称创建EntityManagerFactory。

 entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");

2. EntityManagerFactory对象 

EntityManagerFactory 接口主要用来创建 EntityManager 实例

entityManager = entityManagerFactory.createEntityManager();

由于EntityManagerFactory 是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory 对象不会有线程安全问题),并且EntityManagerFactory 的创建极其浪费资源,所以在使用JPA编程时,我们可以对EntityManagerFactory 的创建进行优化,只需要做到一个工程只存在一个EntityManagerFactory 即可。 

3. EntityManager对象

在 JPA 规范中, EntityManager是完成持久化操作的核心对象。实体类作为普通 java对象,只有在调用 EntityManager将其持久化后才会变成持久化对象。EntityManager对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。

我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作。

方法说明:

getTransaction : 获取事务对象

persist : 保存操作

merge : 更新操作

remove : 删除操作

find/getReference : 根据id查询(立即加载/延迟加载)

4. EntityTransaction对象

在 JPA 规范中, EntityTransaction是完成事务操作的核心对象,对于EntityTransaction在我们的java代码中承接的功能比较简单。

方法说明:

begin:开启事务

commit:提交事务

rollback:回滚事务

四.JPAUtils工具类

public class JPAUtils {
    private static EntityManagerFactory entityManagerFactory;
    static {
         entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
    }

    public static EntityManager getEntityManager() {
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        return entityManager;
    }
}

 五.使用JPA完成增删改查操作

1. 保存 

    @Test
    public void testAdd() {
        Customer customer = new Customer();
        customer.setCustName("阿里巴巴");
        customer.setCustIndustry("互联网");
        customer.setCustLevel("VIP客户");
        customer.setCustSource("网络");
        customer.setCustAddress("杭州");
        customer.setCustPhone("010-84389340");
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            entityManager = JPAUtils.getEntityManager();
            transaction = entityManager.getTransaction();
            transaction.begin();
            entityManager.persist(customer);
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }
    }

2. 修改

    @Test
    public void testMerge() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            entityManager = JPAUtils.getEntityManager();
            transaction = entityManager.getTransaction();
            transaction.begin();
            Customer customer = entityManager.find(Customer.class, 1L);
            customer.setCustPhone("888888");
            entityManager.merge(customer);
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }
    }

3. 删除

    @Test
    public void testRemove() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
             entityManager = JPAUtils.getEntityManager();
             transaction = entityManager.getTransaction();
             transaction.begin();
             Customer customer = entityManager.find(Customer.class, 1L);
             entityManager.remove(customer);
             transaction.commit();
        }
        catch (Exception e) {
            e.printStackTrace();
            transaction.rollback();
        }finally {
            entityManager.close();
        }
    }

4. 根据id查询 

    @Test
    public void testFind() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
             entityManager = JPAUtils.getEntityManager();
             transaction = entityManager.getTransaction();
             transaction.begin();
            Customer customer1 = entityManager.find(Customer.class, 1L);
            Customer customer2 = entityManager.find(Customer.class, 1L);
            //证实了entityManager有缓存
            System.out.println(customer1==customer2);
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }

六.JPA中的复杂查询

JPQL全称Java Persistence Query Language

基于首次在EJB2.0中引入的EJB查询语言(EJB QL),Java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。

其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。

1. 查询全部

    @Test
    public void findAll() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            entityManager = JPAUtils.getEntityManager();
            transaction = entityManager.getTransaction();
            transaction.begin();
            //创建query对象
//          Query query = entityManager.createQuery("select c from Customer c");
            Query query = entityManager.createQuery("from Customer");
            //得到集合返回类型
            List resultList = query.getResultList();
            for (Object o : resultList) {
                System.out.println(o);
            }
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }
    }

2. 分页查询

    @Test
    public void findPage() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            entityManager = JPAUtils.getEntityManager();
            transaction = entityManager.getTransaction();
            transaction.begin();
            Query query = entityManager.createQuery("from Customer");
            //当前页
            query.setFirstResult(0);
            //每页显示条数
            query.setMaxResults(2);
            List resultList = query.getResultList();
            for (Object o : resultList) {
                System.out.println(o);
            }
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }
    }

3. 条件查询

    @Test
    public void testCondition() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            entityManager = JPAUtils.getEntityManager();
            transaction = entityManager.getTransaction();
            transaction.begin();
            Query query =  entityManager.createQuery("from Customer where custName = ?");
            query.setParameter(1, "阿里巴巴");
            //得到唯一的结果集对象
            Object object = query.getSingleResult();
            System.out.println(object);
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }
    }

4. 排序查询

    @Test
    public void testOrder() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            entityManager = JPAUtils.getEntityManager();
            transaction = entityManager.getTransaction();
            transaction.begin();
            Query query =  entityManager.createQuery("from Customer order by custId desc");
            List resultList = query.getResultList();
            for (Object o : resultList) {
                System.out.println(o);
            }
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }
    }

5. 统计查询

    @Test
    public void findCount() {
        EntityManager entityManager = null;
        EntityTransaction transaction = null;
        try {
            entityManager = JPAUtils.getEntityManager();
            transaction = entityManager.getTransaction();
            transaction.begin();
            Query query =  entityManager.createQuery("select count(custId) from Customer");
            Object object = query.getSingleResult();
            System.out.println(object);
            transaction.commit();
        }catch (Exception e) {
            transaction.rollback();
            e.printStackTrace();
        }finally {
            entityManager.close();
        }
    }

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值