• JPA 基础


    JPA 基础

    数据库驱动 ==> JDBC 规范 ==> ORM 框架 ==> JPA 规范 ==> spring-data-jpa

    ORM 思想

    JPA 的使用步骤

    jpa 依赖

    <properties>
        <project.hibernate.version>5.4.2.Final</project.hibernate.version>
    </properties>
    
    <!-- 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 and MariaDB -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    

    jpa 的持久化配置

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
        <!-- 持久化单元 -->
        <persistence-unit name="myJPA" transaction-type="RESOURCE_LOCAL">
            <!-- JPA 的实现者 -->
            <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    
            <properties>
                <!-- 数据库信息
                        驱动        javax.persistence.jdbc.driver
                        数据库地址   javax.persistence.jdbc.url
                        用户名    javax.persistence.jdbc.user
                        密码     javax.persistence.jdbc.password
                 -->
                <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
                <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa_db" />
                <property name="javax.persistence.jdbc.user" value="root" />
                <property name="javax.persistence.jdbc.password" value="root" />
    
                <!-- jpa 实现者的配置
                        显示 sql :   hibernate.show_sql
                        格式化 sql : hibernate.format_sql
                        创建表: hibernate.hbm2ddl.auto 库必须存在,hibernate 不会自动创建库
                            create: 运行时创建,有则先删除再创建
                            update: 运行时创建,有则不创建
                            none:   不创建
                -->
                <property name="hibernate.show_sql" value="true" />
                <property name="hibernate.format_sql" value="true" />
                <property name="hibernate.hbm2ddl.auto" value="update" />
    
            </properties>
    
        </persistence-unit>
    </persistence>
    

    实体类

    package com.mozq.jpa.domain;
    
    import org.hibernate.annotations.GeneratorType;
    
    import javax.persistence.*;
    
    @Entity
    @Table
    public class Customer {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long custId;
        @Column
        private String custName;
        @Column
        private String custSource;
        @Column
        private String custLevel;
        @Column
        private String custIndustry;
        @Column
        private String custPhone;
        @Column
        private String custAddress;
    	//省略构造器和 get/set
    }
    

    使用 jpa 的 API 进行操作

    JPA实体的四种状态 https://www.jianshu.com/p/636954880af8

    JPA中的实体对象拥有四种状态:

    • 瞬时状态(transient)
    • 持久状态(persistent)
    • 游离状态(detached)
    • 删除状态 (deleted)

    瞬时状态

    瞬时状态的实体就是一个普通的java对象,和持久化上下文无关联,数据库中也没有数据与之对应。

    托管状态

    使用 EntityManager 进行 find 或者 persist 操作返回的对象即处于托管状态,此时该对象已经处于持久化上下文中,因此任何对于该实体的更新都会同步到数据库中。

    游离状态

    当事务提交后,处于托管状态的对象就转变为了游离状态。此时该对象已经不处于持久化上下文中,因此任何对于该对象的修改都不会同步到数据库中。但是数据库中有这个对象对应的记录。

    删除状态

    当调用EntityManger对实体进行delete后,该实体对象就处于删除状态。其本质也就是一个瞬时状态的对象。

    持久:处于持久的对象被 EntityManager 管理,当事务被提交时,则对持久对象的任何修改都将同步到数据库中。

    public interface EntityManager {
        /* 
        	瞬时对象 
        	游离对象将报异常 
        */
        void persist(Object var1); // 对象持久化,交给 EntityManager 管理。数据库中必须不存在。瞬时 ==> 持久
        <T> T merge(T var1);// 根据 id 是否存在,插入新对象或更新现有对象。瞬时 ==> 持久 / 游离 ==> 持久
        
        void remove(Object var1);
        <T> T find(Class<T> entityClass, Object id);// 立即加载,返回真实对象
        <T> T getReference(Class<T> entityClass, Object id);// 延迟加载,返回代理对象
        
        void flush();
        /* obj 必须是受管对象,用于将数据库数据同步到受管对象,如果是其他状态的对象将抛异常。*/
        void refresh(Object var1); 
        void clear();
        void detach(Object var1);
        
        void close();//关闭
        EntityTransaction getTransaction();// 获取事务对象
    }
    
    # void refresh(Object var1);
    java.lang.IllegalArgumentException: Entity not managed
    
    # persist 方法异常
    Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.mozq.jpa.domain.Customer
    
    Customer customer = new Customer();
    customer.setCustId(1L);
    customer.setCustName("刘备");
    em.persist(customer);//此时数据库中存在 1L 记录,报错。
    
    @Test
    public void testSave(){
        // Persistence 创建实体类管理器工厂
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJPA");
        // 实体类管理器
        EntityManager em = factory.createEntityManager();
        // 事务对象
        EntityTransaction tx = em.getTransaction();
        tx.begin();
    
        // CRUD
        Customer customer = new Customer();
        customer.setCustName("刘备");
    
        em.persist(customer); // 保存
    
        tx.commit();
        // 释放资源
        em.close();
        factory.close();
    }
    

    JPQL 查询

    // 查询全部
    Query query = em.createQuery("from Customer");
    List resultList = query.getResultList();
    System.out.println(resultList);
    
    // 排序
    Query query = em.createQuery("from Customer order by custAddress desc ,custName asc, custId");
    List resultList = query.getResultList();
    /*
        order by
            customer0_.custAddress desc,
            customer0_.custName asc,
            customer0_.custId
    */
    
    // 分页
    Query query = em.createQuery("from Customer order by custId");
    query.setFirstResult(2);
    query.setMaxResults(3);
    /*
      order by
            customer0_.custId limit ?, ?
    */
    

    Hibernate 主键生成策略和创建表策略

    public enum GenerationType {
        TABLE,
        SEQUENCE,
        IDENTITY,
        AUTO;
    
        private GenerationType() {
        }
    }
    hibernate.hbm2ddl.auto create/update/none
    
    # <property name="hibernate.hbm2ddl.auto" value="create" /> # 先删除表,再创建表
    # @GeneratedValue(strategy = GenerationType.IDENTITY)
    drop table if exists Customer
    create table Customer (
        custId bigint not null auto_increment, # 使用自增主键,生成的 sql 不会有主键字段。需要数据库支持自增。
        custAddress varchar(255),
        custIndustry varchar(255),
        custLevel varchar(255),
        custName varchar(255),
        custPhone varchar(255),
        custSource varchar(255),
        primary key (custId)
    ) engine=InnoDB
    insert 
    into
        Customer
        (custAddress, custIndustry, custLevel, custName, custPhone, custSource) 
    values
        (?, ?, ?, ?, ?, ?)
    
    # <property name="hibernate.hbm2ddl.auto" value="update" />
    # @GeneratedValue(strategy = GenerationType.IDENTITY) # 使用自增主键,生成的 sql 不会有主键字段。需要数据库支持自增。
        create table Customer ( # 如果表不存在则会发送创建表的语句。
            custId bigint not null auto_increment,
            custAddress varchar(255),
            custIndustry varchar(255),
            custLevel varchar(255),
            custName varchar(255),
            custPhone varchar(255),
            custSource varchar(255),
            primary key (custId)
        ) engine=InnoDB
        insert 
        into
            Customer
            (custAddress, custIndustry, custLevel, custName, custPhone, custSource) 
        values
            (?, ?, ?, ?, ?, ?)
    

    GenerationType.AUTO + create

    drop table if exists Customer
    drop table if exists hibernate_sequence
    
    create table Customer (
        custId bigint not null,
        custAddress varchar(255),
        custIndustry varchar(255),
        custLevel varchar(255),
        custName varchar(255),
        custPhone varchar(255),
        custSource varchar(255),
        primary key (custId)
    ) engine=InnoDB
    
    create table hibernate_sequence (
        next_val bigint
    ) engine=InnoDB
    
    insert into hibernate_sequence values ( 1 )
    
    select
            next_val as id_val 
        from
            hibernate_sequence for update 锁
            
    update
        hibernate_sequence 
    set
        next_val= ? 
    where
       next_val=?
    
    insert into
        Customer
            (custAddress, custIndustry, custLevel, custName, custPhone, custSource, custId) 
        values
            (?, ?, ?, ?, ?, ?, ?)
    

    JPA

    Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.mozq.jpa.domain.Customer
    
  • 相关阅读:
    LintCode Python 简单级题目 488.快乐数
    LintCode Python 简单级题目 100.删除排序数组中的重复数字 101.删除排序数组中的重复数字II
    LintCode Python 简单级题目 373.奇偶分割数组
    LintCode Python 简单级题目 39.恢复旋转排序数组
    LintCode Python 简单级题目 35.翻转链表
    LintCode Python 简单级题目 451.两两交换链表中的节点
    LintCode Python 简单级题目 174.删除链表中倒数第n个节点
    aws查看官方centos镜像imageid
    linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计
    php配置优化-生产环境应用版
  • 原文地址:https://www.cnblogs.com/mozq/p/11283615.html
Copyright © 2020-2023  润新知