zoukankan      html  css  js  c++  java
  • JPA 基本使用

    ORM简介

    对象关系映射(Object Relational Mapping,简称ORM),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

    实现ORM思想的框架:Mybatis Hibernate

    ORM优点

    ORM框架自动实现Entity实体的属性与关系型数据库字段的映射。CRUD的工作则可以交给ORM来自动生成代码方式实现。隐藏了数据访问细节,“封闭”的通用数据库交互,他使得我们的通用数据库交互变得简单易行,并且完全不用考虑SQL语句。大大提高我们开发效率, 这样一来也减少我们维护一个复杂 缺乏灵活性数据访问层的成本。

    JPA简介

    JPA是Java Persistence API的简称,中文名Java持久层API,内部是由一系列接口和抽象类构成。JDK通过注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。Sun引入新的JPA规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一。

    依赖配置

            <!-- 集成c3p0连接池到Hibernate ORM -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-c3p0</artifactId>
                <version>5.4.2.Final</version>
            </dependency>
    
            <!-- hibernate对jpa的支持包 -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>5.0.7.Final</version>
            </dependency>
    
            <!-- Mysql -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.16</version>
            </dependency>
    

    JPA核心配置文件

    1. 位置:META-INF 的文件夹下(resources目录下)
    2. 命名:persistence.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">  <!-- 导入约束 -->
    
        <!-- transaction-type:
            JPA:分布式事务管理
            RESOURCE_LOCAL:本地事务管理 -->
        <persistence-unit name="myjpa" transaction-type="RESOURCE_LOCAL">
            <!--jpa实现-->
            <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
            <!--数据库信息-->
            <properties>
                <property name="javax.persistence.jdbc.user" value="root"></property>
                <property name="javax.persistence.jdbc.password" value="root"></property>
                <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
                <property name="javax.persistence.jdbc.url"
                          value="jdbc:mysql://localhost:3306/littledonkey?serverTimezone=GMT%2B8&useSSL=false"></property>
                          
                <!--jpa实现方的配置-->
                <!--显示sql,打印到控制台-->
                <property name="hibernate.show_sql" value="true"></property>
                <!--自动创建数据库表-->
                <!--配置jpa实现方(hibernate)的配置信息
                    显示sql              :   false|true
                    自动创建数据库表      :  hibernate.hbm2ddl.auto
                        create      : 程序运行时创建数据库表(如果有表,先删除表再创建)
                        update      :程序运行时创建表(如果有表,不会创建表)
                        none        :不会创建表-->
                <property name="hibernate.hbm2ddl.auto" value="update"></property>
            </properties>
        </persistence-unit>
    </persistence>
    

    主从表

    一对多:一是主表
    多对多:关系维护方是主表
    

    实体类对象(配置对象和表的映射关系)(一对多)

    /**
     * 老板
     */
    @Entity
    @Table(name = "boss")   //对应表名
    public class Boss {
    
        /**
         * @Id:声明主键的配置
         * @GeneratedValue:配置主键的生成策略 strategy
         *      GenerationType.IDENTITY :自增(底层数据库需支持自动增长,对id自增)
         *
         *      JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO. 
         *          TABLE:jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增。 
         *          SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。 (oracle)
         *          IDENTITY:主键由数据库自动生成(主要是自动增长型) (mysql)
         *          AUTO:由程序自动的帮助我们选择主键生成策略。
         *
         * @Column:配置属性和字段的映射关系 
         *      name:数据库表中字段的名称
         */
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "boss_id")
        private Long bossId;
        @Column(name = "boss_name")
        private String bossName;
    
        /**
         * 配置外键(外键引用的那个列在主表中必须是主键列或者唯一列。外键设在从表('多'的一方))
         * 
         * 使用注解的形式配置多表关系
         *            1.声明关系
         *                @OneToMany : 配置一对多关系
         *                    targetEntity :对方对象的字节码对象
         *            2.配置外键
         *                @JoinColumn : 配置外键
         *                    name:从表(多的一方)外键字段名称(不设置name的值,则在默认情况下,name=从表名称+“_”+从表主键的字段名)
         *                    referencedColumnName:主表的主键字段名称
         *                    unique:是否唯一。默认值不唯一
         *                    nullable:是否允许为空。默认值允许。
         *                    insertable:是否允许插入。默认值允许。
         *                    updatable:是否允许更新。默认值允许。
         *                    columnDefinition:列的定义信息。
         *
         * 在一的一方添加了外键了配置,所以对于boss而言,也具备了维护外键的作用
         *
         *
         * @OneToMany:
         *     作用:建立一对多的关系映射
         *     属性:
         *     	targetEntityClass:指定多的多方的类的字节码
         *     	mappedBy:指定从表实体类中配置外键(多表关系)的属性名称。(用于放弃维护权)
         *     	cascade:指定要使用的级联操作
         *     	fetch:指定是否采用延迟加载
         *              EAGER   :立即加载
         *              LAZY    :延迟加载
         *     	orphanRemoval:是否使用孤儿删除
         */
    
        //@OneToMany(targetEntity = Customer.class,cascade = CascadeType.ALL)
        //@JoinColumn(name = "cus_boss_id",referencedColumnName ="boss_id" )
        @OneToMany(mappedBy = "myBoss",cascade = CascadeType.ALL)     //放弃维护权
        private Set<Customer> customers=new HashSet<>();
    }
    
    
    /**
     * 顾客
     */
    @Entity
    @Table(name = "customer")
    public class Customer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "cus_id")
        private Long cusId;     //(主键)
        @Column(name = "cus_name")
        private String cusName;
    
        /**
         * 配置顾客到老板的多对一关系
         *     使用注解的形式配置多对一关系
         *      1.配置表关系
         *          @ManyToOne : 配置多对一关系
         *              targetEntity:对方的实体类字节码
         *      2.配置外键
         *
         * 配置外键的过程,配置到了多的一方,就会在多的一方维护外键
         *
         */
        @ManyToOne(targetEntity = Boss.class,fetch = FetchType.LAZY)
        @JoinColumn(name = "cus_boss_id",referencedColumnName = "boss_id")
        private Boss myBoss;
    }
    

    实体类对象(配置对象和表的映射关系)(多对多)

    /**
     * 多对多
     */
    public class User {
    
        @ManyToMany(targetEntity = Role.class)
        @JoinTable(name = "user_role",     //中间表名称
                   joinColumns ={ @JoinColumn(name = "sys_user_id",referencedColumnName="user_id") },     //当前对象在中间表的外键
                   inverseJoinColumns = { @JoinColumn(name = "sys_role_id",referencedColumnName="role_id") } )     //对方对象在中间表的外键
        1、关系维护端,负责多对多关系的绑定和解除
        2、@JoinTable注解的name属性指定关联表的名字
        3、joinColumns指定外键的名字,关联到关系维护端(User)
        4、inverseJoinColumns指定外键的名字,要关联的关系被维护端(role)
        5、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
            即表名为user_role
            关联到主表的外键名:主表名+下划线+主表中的主键列名,即user_user_id
            关联到从表的外键名:从表名+下划线+从表的主键列名,即role_role_id
            主表就是关系维护端(User)对应的表,从表就是关系被维护端对应的表
        private Set<Role> myRoles;
    }
    
    /**
     * 放弃维护权:@ManyToMany(mappedBy = "myRole",cascade = CascadeType.ALL)
     * 注:添加在放弃维护权的一方,mappedBy引用维护权方配置外键(多对多关系)的属性名称。
     */
    class test {
        public void test(){
            User user = new User();
            Role role = new Role();
            /**
             * 配置用户到角色的关系,可以对中间表的数据进行维护
             *
             * 不能两个表都对中间表进行维护,否则会主键重复,需要一方放弃维护权
             */
            user.getRoles().add(role);
    
            //先保存主表,再保存从表
            userDao.save(user);
            roleDao.save(role);
        }
    }
    
    /**
     * 级联操作:cascade = CascadeType.ALL(在操作主体的实体类(user)上配置)
     */
    class test {
        public void test(){
            User user = new User();
            Role role = new Role();
            user.getRoles().add(role);
    
            userDao.save(user);
        }
    }
    

    使用步骤

        public void test() {
    
            /**
             * Persistence:用于加载配置文件,创建实体管理器工厂
             *
             * EntityManagerFactory:用于创建实体管理器(创建过程比较浪费资源)
             *      特点:线程安全的对象
             *      解决创建过程耗时问题:静态代码块创建公共对象 
             *
             * EntityManager:获取事务,以及持久化数据库的操作
             *
             * 方法说明:
             * 	getTransaction : 获取事务对象
             * 	persist : 保存操作
             * 	merge : 更新操作
             * 	remove : 删除操作
             * 	find/getReference : 根据id查询
             */
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("myjpa");
            EntityManager entityManager = emf.createEntityManager();
            EntityTransaction et = entityManager.getTransaction();
            et.begin();
            Customer customer = new Customer();
            customer.setCustName("小红");
            customer.setCustAddress("北京");
            entityManager.persist(customer);
            et.commit();
            entityManager.close();
            emf.close();
        }
    

    基本语法

        简单查询
    
        /**
         * find : 根据id查询数据
         *       class:查询数据的结果需要包装的实体类类型的字节码
         *       id:查询的主键的取值
         *       entityManager.find(Customer.class, 1l)
         *
         *
         * getReference方法(延迟加载(懒加载))
         *        1.获取的对象是一个动态代理对象
         *        2.调用getReference方法不会立即发送sql语句查询数据库
         *          当调用查询结果对象的时候,才会发送查询的sql语句:什么时候用,什么时候发送sql语句查询数据库
    
         * 调用remove方法完成删除操作
         *         entityManager.remove(customer);
         *
         * 更新操作
         *         merge(customer);
         *
         * 保存操作 : persist
         */
    
    
        复杂查询(jpql:查询语句写实体类与实体类属性)(sql:写表与表的字段)
    
        /**查询全部
         *          创建query对象
         * 			String jpql = "from Customer";
         * 			Query query = em.createQuery(jpql);
         * 			查询并得到返回结果,得到集合返回类型
         * 			List list = query.getResultList();
         *
         * 分页查询
         *          创建query对象
         * 			String jpql = "from Customer";
         * 			Query query = em.createQuery(jpql);
         * 			//起始索引
         * 			query.setFirstResult(0);
         * 			//每页显示条数
         * 			query.setMaxResults(2);
         * 			//查询并得到返回结果,得到集合返回类型
         * 			List list = query.getResultList();
         *
         * 条件查询
         *          创建query对象
         * 			String jpql = "from Customer where custName like ? ";
         * 			Query query = em.createQuery(jpql);
         * 			//对占位符赋值,从1开始
         * 			query.setParameter(1, "传智播客%");   //以传智播客开头
         * 			//查询并得到返回结果
         * 			Object object = query.getSingleResult();
         *
         * 排序查询: 倒序查询全部客户(根据id倒序)
         *          sql:SELECT * FROM customer ORDER BY cust_id DESC
         *          jpql:from Customer order by custId desc
         *
         * 统计查询
         *          String jpql = "select count(custId) from Customer";
         * 			Query query = em.createQuery(jpql);
         * 			// 2.查询并得到返回结果
         * 			Object count = query.getSingleResult();
         */
    
  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/loveer/p/11379473.html
Copyright © 2011-2022 走看看