• 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();
         */
    
  • 相关阅读:
    插入排序实现
    冒泡排序的实现
    选择排序的实现方法
    实现文字的竖排
    一个实体类的定义
    将字符串中的非字母数字,转化为ascii码输出
    根据员工入职时间和合同期计算下一次合同签订时间
    centos安装java的问题解决
    弓箭射小人
    Nature & Science 20102011年全部期刊下载链接
  • 原文地址:https://www.cnblogs.com/loveer/p/11379473.html
Copyright © 2020-2023  润新知