jpa的使用

本文章只是自己在学习中记的笔记(可能有点乱),只提供参考。如有错误请指出

什么是jpa

JPA (Java Persistence API)Java持久化API。是一套Sun公司Java官方制定的ORM方案,是规范,是标准 ,sun公司自己并没有实现

  • ORM是什么

    对象关系映射,ORM是一个实现使用对象操作数据库的设计思想,主要目的是操作实体类就相当于操作数据库。不再重点关注sql语句。

  • JPA的实现者

    JPA只是是一套标准。它只是一套实现ORM理论的接口。没有实现的代码。那么我们必须要有具体的实现者才可以完成ORM操作功能的实现!

    市场上的主流的JPA框架(实现者)有:

    • Hibernate (JBoos)
    • EclipseTop(Eclipse社区)
    • OpenJPA (Apache基金会)

Hibernate实现

hibernate是一个开放源码的对象关系映射框架

  1. 它对jdbc进行了非常轻量级的对象封装。

  2. 它将实体类与数据库表建立映射关系,是一个全自动的orm框架。

案例说明

对用户的增删改查操作

  • 项目搭建

    导入对应的maven坐标

    
            
                org.hibernate
                hibernate-entitymanager
                5.4.10.Final
            
    
            
            
                org.hibernate
                hibernate-c3p0
                5.4.10.Final
            
            
            
                mysql
                mysql-connector-java
                8.0.19
            
            
            
                log4j
                log4j
                1.2.17
            
            
            
                org.projectlombok
                lombok
                1.18.12
                provided
            
    
  • 配置相关的jpa配置文件

    1. 配置文件在类路径下的一个叫META-INF的文件下。

    2. 它的文件命名也有要求。叫persistence.xml

      
      
          
          
              
              org.hibernate.jpa.HibernatePersistenceProvider
              
              
              
                  
                  
                  
                  
      
                  
                  
                  
      
              
          
      
      
      • 配置持久化数据单元。

        1. name是 持久化单元名称,名称可以随便写,后面我们在程序中就是更具这名称获取对象。
        2. transaction-type事务管理的方式,它有2个选项:
        • RESOURCE_LOCAL: 本地事务管理。
        • JPA: 分布式事务管理。
      • org.hibernate.jpa.HibernatePersistenceProviderjpa的实现方式。因为jpa是接口,是规范,它没有对数据库的操作的实现。所以我们还要选择是那种方法实现jpa操作。这里是选用了hibernate方式。

      • 里配置的是数据库信息。

        注意:其中数据库的信息字段,都要以javax.persistence.jdbc.开头。

   再后面2个属性,可配可不配,它是配置jpa实现放的配置信息,也就是hibernate。

   重点说下`hibernate.hbm2ddl.auto`,自动创建数据库表。它有3个可选对象。

   - create:程序运行时创建数据库表(如果有表,先删除再创建)
   - update:程序运行时再创建表(如果有表不会创建)
   - none:不会创建表。
  • 创建实体类

    @AllArgsConstructor
    @NoArgsConstructor
    @Setter
    @Getter
    @ToString
    //--------上面是lombok的注解--------
    @Entity
    @Table(name="User")
    public class User {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private Integer id;
        private String name;
        private String pwd;
        @Column(name = "create_time")
        private Date createTime;
    
    }
    

    注意:上面我用到了lombok。还有,所有的非lombok注解都是javax.persistence.*里的

    上面的注解是配置映射关系。映射关系的配置有两个方向:

    • 实体类和表的映射:
      1. @Entity:声明此类是一个实体类。
      2. @Table(name="User"):对应的是数据库中的表。name就是数据库中的表名
    • 实例类中属性和表中的字段映射:
      1. @Id:主键。
      2. @GeneratedValue(strategy = GenerationType.IDENTITY):定义的主键生成策略,其中有:
        • GenerationType.IDENTITY:自增。底层数据库必须支持自增才可以使用。像mysql。
        • GenerationType.SEQUENCE:序列。底层数据库必须支持序列才可以使用,像orac就支持,mysql不支持
        • GenerationType.TABLE:jpa提供的一种机制,它通过一张表的形式完成自增操作。(会在数据库中创建一张表),通过这张表来维护自增
        • GenerationType.AUTO:程序自动的选择主键策略。根据自己的表或运行环境选择上面三种策略。
      3. @Column(name = "id"):表中的字段映射,name,数据库中对应的字段名。
  • api操作

    • 增加操作

          @Test
          public void test() {
              //1.加载配置文件创建工厂(实体管理类工厂)对象,传入的是持久化数据单元,也就是配置文件里我们配置的数据单元。
              EntityManagerFactory jpa = Persistence.createEntityManagerFactory("myJpa");
      
              //2.通过工厂获取实体管理器
              EntityManager manager = jpa.createEntityManager();
      
              //获取事务对象
              EntityTransaction tx = manager.getTransaction();
              tx.begin();//开启事务
              //完成增删改查
              User User = new User();
              user.setName("nihao");
              user.setPwd("123");
              user.setCreateTime(new Date());
      
              //保存
              manager.persist(user);//保存操作
      
              //提交事务
              tx.commit();
      
              //关闭资源
              manager.close();
              jpa.close();
          }
      
  • 根据id查询用户

    引入一个概念,上面频繁通过工厂获取实体管理器,是一个比较耗资源和耗时的操作。所以我们可以把它放到一个静态代码块中,封装成一个工具类来获取,解决耗资源和耗时问题

    public class JpaUtils {
        private static EntityManagerFactory factory;
    
        static {
            factory = Persistence.createEntityManagerFactory("myJpa");
        }
    
        /*获取实体类管理器对象*/
        public static EntityManager getEntityManager(){
            return factory.createEntityManager();
        }
    
    }
    

    那么我们根据id查询代码实现:

     @Test
        public void test2() {
            //获取EntityManager对象
            EntityManager entityManager = JpaUtils.getEntityManager();
            //查询不需要事务,所以不用开启事务。
            //根据id查询操作
            /*
             * 要传入2个参数
             * class:查询数据的结果需要包装的实体类型的字节码
             * id:查询的主键的信息
             * */
    //        User user = entityManager.find(User.class, 1);//查询的第一种方法find();
            User user = entityManager.getReference(User.class, 1);//第二种方法。参数代表的类型都一样。
            /*
             * 这2种方法的区别有什么不一样?
             * find():查询的对象就是当前Userr本身。再调用的时候,sql发送的时机是立刻去数据库查询
             * getReference():查询的对象是一个代理类对象。sql发送的时机是什么时候调用,就什么时候发送。
             * 一般是使用getReference(),延迟加载方式。
             * */
            System.out.println(user);
            //释放EntityManager资源
            entityManager.close();
    
        }
    

    其中entityManager.findentityManager.getReference的作用和结果都是一样的。为啥要定义两个方法?

    • find():查询的对象就是当前User本身。再调用的时候,sql发送的时机是立刻去数据库查询
    • getReference():查询的对象是一个代理类对象。sql发送的时机是什么时候调用,就什么时候发送。(延迟加载)

    我们一般是使用getReference(),延迟加载方式来使用。

  • 删除客户的操作

      @Test
        public void testRemove() {
            EntityManager entityManager = JpaUtils.getEntityManager();
            //开启事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();//开启事务的操作
            //删除操作
            // 操作步骤
            /*
             * 1,先根据id查询到用户
             * 2,传入查询到的用户进行删除
             * */
            User User = entityManager.getReference(User.class, 2);
            entityManager.remove(User);
            tx.commit();
            entityManager.close();
        }
    
  • 更新操作

     @Test
        public void testUpdate() {
            EntityManager entityManager = JpaUtils.getEntityManager();
    
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
    
            User User = entityManager.getReference(User.class, 2);
            User.setName("我我我我");
    
            //更新操作
            entityManager.merge(User);
            tx.commit();
            entityManager.close();
        }
    

    如果实体类中有写属性没值,那么更新操作后数据库那些字段也会没值。

  • 查询所有的操作

    @Test
        public void testFindAll() {
            EntityManager entityManager = JpaUtils.getEntityManager();
    
            //查询全部jqpl
            /*
             * jqpl:form User
             * sql:select * from User
             * */
            String jpql = "from User";
            Query query = entityManager.createQuery(jpql);
            //发送查询,并封装结果集
            List list = query.getResultList();
            for (User o : list) {
                System.out.println(o);
            }
    
            entityManager.close();
        }
    

    这里引入了一个jpql

    sql:是查询表和表中的字段。

    jpql:是查询的实体类和类中的属性

    它们两的语法相识。

    比如:

    jqpl:form User
    sql:select * from User
    
  • 倒序查询全部用户,根据id倒序

      EntityManager entityManager = JpaUtils.getEntityManager();
    
            String jpql = "from User order by id desc";
            Query query = entityManager.createQuery(jpql);
    
            List resultList = query.getResultList();
    
            for (User User : resultList) {
                System.out.println(User);
            }
            entityManager.close();
    
  • 使用jpql查询用户的总数

    @Test
    public void testCount() {
        EntityManager entityManager = JpaUtils.getEntityManager();
        String jpql = "select count(id) from User ";
        Query query = entityManager.createQuery(jpql);
        Object singleResult = query.getSingleResult();//获取一个结果的。
    
        System.out.println(singleResult);
        entityManager.close();
    }
    
  • 分页查询

    EntityManager entityManager = JpaUtils.getEntityManager();
            String jpql = "from User";
            //1.根据jpql创建query对象
            Query query = entityManager.createQuery(jpql);
            //2.对参数负赋值--分页参数
            query.setFirstResult(4);//起始索引,从0开始查,不包含0
            query.setMaxResults(2);//每页查询的条数
    
            List resultList = query.getResultList();
    
            for (User User : resultList) {
                System.out.println(User);
            }
    
            entityManager.close();
    
  • 条件查询

     @Test
        public void testLike() {
            EntityManager entityManager = JpaUtils.getEntityManager();
            String jpql = "from User where name like ?1";
            //1.根据jpql创建query对象
            Query query = entityManager.createQuery(jpql);
            /*
             * 第一个参数是占位符的位置,默认是1开始
             * 第二个是 取值
             * */
            query.setParameter(1, "ni%");
            List resultList = query.getResultList();
    
            for (User User : resultList) {
                System.out.println(User);
            }
    
            entityManager.close();
        }
    

    String jpql = "from User where name like ?1"中,占位符后是hpa的样式规定,有多个占位符,比如name like ?1 or pwd = ?2这样写,后面的数字是你设置占位符里的值的时候根据这数字去设置值。像query.setParameter(1, "ni%");

你可能感兴趣的:(jpa的使用)