A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© Mylo 黑马粉丝团   /  2019-3-21 16:52  /  860 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

入门
  • 导入依赖

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.hibernate.version>5.0.7.Final</project.hibernate.version>
</properties>

<dependencies>
    <!-- junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <!-- 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>

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

    <!-- Mysql and MariaDB -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
</dependencies>
  • 创建数据库表

CREATE TABLE cst_customer (
    cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
    cust_name varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
    cust_source varchar(32) DEFAULT NULL COMMENT '客户信息来源',
    cust_industry varchar(32) DEFAULT NULL COMMENT '客户所属行业',
    cust_level varchar(32) DEFAULT NULL COMMENT '客户级别',
    cust_address varchar(128) DEFAULT NULL COMMENT '客户联系地址',
    cust_phone varchar(64) DEFAULT NULL COMMENT '客户联系电话',
    PRIMARY KEY (`cust_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  • ==编写实体类和数据库表的映射配置[重点]==

import javax.persistence.*;
import java.io.Serializable;

@Entity // 声明实体类是JPA的ORM类
@Table(name = "cst_customer") // 指定该类与哪个表映射
public class Customer implements Serializable {

    @Id // 指定主键
    @Column(name = "cust_id") // 指定映射的列
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 配置主键的生成策略
    private Long custId;
    @Column(name = "cust_name")
    private String custName;
    @Column(name = "cust_source")
    private String custSource;
    @Column(name = "cust_industry")
    private String custIndustry;
    @Column(name = "cust_level")
    private String custLevel;
    @Column(name = "cust_address")
    private String custAddress;
    @Column(name = "cust_phone")
    private String custPhone;

    "setter and getter methods"
}
  • 常用注解的说明
    • @Entity
      • 作用:指定当前类是实体类

    • @Table
      • 作用:指定实体类和表之间的对应关系
      • 属性:
        • name:指定数据库表的名称


    • @Id
      • 作用:指定当前字段是主键

    • @GeneratedValue
      • 作用:指定主键的生成方式
      • 属性:
        • strategy :指定主键生成策略


    • @Column
      • 作用:指定实体类属性和数据库表之间的对应关系
      • 属性:
        • name:指定数据库表的列名称
        • unique:是否唯一
        • nullable:是否可以为空
        • inserttable:是否可以插入
        • updateable:是否可以更新
        • columnDefinition: 定义建表时创建此列的DDL
        • secondaryTable: 从表名
          • 如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字搭建开发环境




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


<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             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/test"/>
            <!-- 数据库用户名 -->
            <property name="javax.persistence.jdbc.user" value="root"/>
            <!-- 数据库密码 -->
            <property name="javax.persistence.jdbc.password" value="root"/>

            <!--jpa提供者的可选配置:我们的JPA规范的提供者为hibernate,所以jpa的核心配置中兼容hibernate的配 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>
    </persistence-unit>
</persistence>@Test
public void test01() {
    // 创建实体管理类工厂,借助Persistence的静态方法获取
    // 其中传递的参数为持久化单元名称,需要jpa配置文件中指定
    EntityManagerFactory facotry = Persistence.createEntityManagerFactory("myJpa");
    // 创建实体管理类
    EntityManager manager = facotry.createEntityManager();
    // 获取事务对象
    EntityTransaction tx = manager.getTransaction();
    // 开启事务
    tx.begin();
    // 保存数据
    Customer customer = new Customer();
    customer.setCustName("余浩宏");
    manager.persist(customer);

    // 提交事务
    tx.commit();
    // 释放资源
    manager.close();
    facotry.close();
}JPA中的主键生成策略
  • 键标识为@Id, 其生成规则由@GeneratedValue设定的
  • JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO

  • IDENTITY:主键由数据库自动生成(主要是自动增长型)

@Id  
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long custId;
  • SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列

@Id  
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="payablemoney_seq")  
@SequenceGenerator(name="payablemoney_seq", sequenceName="seq_payment")  
private Long custId;
  • AUTO:主键由程序控制

@Id  
@GeneratedValue(strategy = GenerationType.AUTO)  
private Long custId;
  • TABLE:使用一个特定的数据库表格来保存主键

@Id  
@GeneratedValue(strategy = GenerationType.TABLE, generator="payablemoney_gen")  
@TableGenerator(name = "payablemoney_gen",  
    table="tb_generator",  
    pkColumnName="gen_name",  
    valueColumnName="gen_value",  
    pkColumnValue="PAYABLEMOENY_PK",  
    allocationSize=1  
)
private Long custId;

//@TableGenerator的定义:
@Target({TYPE, METHOD, FIELD})   
@Retention(RUNTIME)  
public @interface TableGenerator {  
  //表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中
  String name();  
  //表示表生成策略所持久化的表名,例如,这里表使用的是数据库中的“tb_generator”。
  String table() default "";  
  //catalog和schema具体指定表所在的目录名或是数据库名
  String catalog() default "";  
  String schema() default "";  
  //属性的值表示在持久化表中,该主键生成策略所对应键值的名称。例如在“tb_generator”中将“gen_name”作为主键的键值
  String pkColumnName() default "";  
  //属性的值表示在持久化表中,该主键当前所生成的值,它的值将会随着每次创建累加。例如,在“tb_generator”中将“gen_value”作为主键的值
  String valueColumnName() default "";  
  //属性的值表示在持久化表中,该生成策略所对应的主键。例如在“tb_generator”表中,将“gen_name”的值为“CUSTOMER_PK”。
  String pkColumnValue() default "";  
  //表示主键初识值,默认为0。
  int initialValue() default 0;  
  //表示每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50。
  int allocationSize() default 50;  
  UniqueConstraint[] uniqueConstraints() default {};  
}

//这里应用表tb_generator,定义为 :
CREATE TABLE  tb_generator (  
  id NUMBER NOT NULL,  
  gen_name VARCHAR2(255) NOT NULL,  
  gen_value NUMBER NOT NULL,  
  PRIMARY KEY(id)  
)JPA的API介绍
  • Persistence对象
    • Persistence对象主要作用是用于获取EntityManagerFactory对象的


EntityManagerFactory factory= Persistence.createEntityManagerFactory(unitName);
  • EntityManagerFactory
    • EntityManagerFactory 接口主要用来创建 EntityManager 实例
    • 由于EntityManagerFactory 是一个线程安全的对象
    • 并且EntityManagerFactory 的创建极其浪费资源
    • 所以在使用JPA编程时,只需要做到一个工程只存在一个EntityManagerFactory 即可


EntityManager em = factory.createEntityManager();
  • EntityManager
    • EntityManager是完成持久化操作的核心对象
    • 实体类作为普通 java对象,只有在调用 EntityManager将其持久化后才会变成持久化对象
    • EntityManager对象在一组实体类与底层数据源之间进行 O/R 映射的管理
    • 我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作


getTransaction : 获取事务对象
persist : 保存操作
merge : 更新操作
remove : 删除操作
find/getReference : 根据id查询
  • EntityTransaction
    • EntityTransaction是完成事务操作的核心对


begin:开启事务
commit:提交事务
rollback:回滚事务抽取JPAUtil工具类import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JPAUtil {

    // JPA的实体管理器工厂
    private static EntityManagerFactory em;

    // 使用静态代码块赋值
    static {
        // 注意:该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致
        em = Persistence.createEntityManagerFactory("myJpa");
    }

    // 使用管理器工厂生产一个管理器对象
    public static EntityManager getEntityManager() {
        return em.createEntityManager();
    }
}使用JPA完成增删改查操作
  • 添加

@Test
public void testAdd() {
    Customer customer = new Customer();
    customer.setCustName("余浩宏");
    customer.setCustLevel("VIP");
    customer.setCustSource("电线杆");
    customer.setCustIndustry("咸鱼");
    customer.setCustAddress("广州市天河区");
    customer.setCustPhone("888888");
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        em.persist(customer);
        tx.commit();
    }catch (Exception ex) {
        ex.printStackTrace();
        if (tx != null) {
            tx.rollback();
        }
    }finally {
        em.close();
    }
}
  • 修改

@Test
public void testMerge() {
    //定义对象
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        Customer customer = em.find(Customer.class, 2L);
        customer.setCustName("余不懂");
        em.clear();//把c1对象从缓存中清除出去
        em.merge(customer);
        tx.commit();
    }catch (Exception ex) {
        ex.printStackTrace();
        if (tx != null) {
            tx.rollback();
        }
    }finally {
        if (em != null) {
            em.close();
        }
    }
}
  • 删除

@Test
public void testRemove() {
    // 定义对象
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        // 获取实体管理对象
        em = JPAUtil.getEntityManager();
        // 获取事务对象
        tx = em.getTransaction();
        // 开启事务
        tx.begin();
        // 执行操作
        Customer c1 = em.find(Customer.class, 1L);
        em.remove(c1);
        // 提交事务
        tx.commit();
    } catch (Exception e) {
        // 回滚事务
        tx.rollback();
        e.printStackTrace();
    } finally {
        // 释放资源
        em.close();
    }
}
  • 查询

public void testGetOne() {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        Customer c1 = em.find(Customer.class, 1L);
        tx.commit();
        System.out.println(c1);
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
    } finally {
        em.close();
    }
}@Test
public void testGetOne() {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        Customer c1 = em.find(Customer.class, 1L);
        Customer c2 = em.find(Customer.class, 1L);
        System.out.println(c1 == c2);// 输出结果是true,EntityManager也有缓存
        tx.commit();
        System.out.println(c1);
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
    } finally {
        em.close();
    }
}@Test
public void testLoadOne() {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        Customer c1 = em.getReference(Customer.class, 1L);
        tx.commit();
        System.out.println(c1);
        "com.study.springDataJpa.Customer@3b2c0e88"
        "得到代理对象"
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
    } finally {
        em.close();
    }
}JPA中的复杂查询
  • JPQL全称Java Persistence Query Language
  • 其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性
  • 查询全部

@Test
public void findAll() {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        // 创建query对象
        String jpql = "from Customer";
        Query query = em.createQuery(jpql);
        // 查询并得到返回结果
        List<Customer> list = query.getResultList(); // 得到集合返回类型
        for (Customer customer : list) {
            System.out.println(customer.getCustName());
        }
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
    } finally {
        em.close();
    }
}
  • 分页

@Test
public void findPaged () {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();

        String jpql = "from Customer";
        Query query = em.createQuery(jpql);
        //起始索引
        query.setFirstResult(0);
        //每页显示条数
        query.setMaxResults(2);
        //查询并得到返回结果
        List<Customer> list = query.getResultList(); //得到集合返回类型
        for (Customer customer : list) {
            System.out.println(customer.getCustName());
        }
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
    } finally {
        em.close();
    }
}
  • 条件

@Test
public void findCondition() {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        String jpql = "from Customer where custName like ? ";
        Query query = em.createQuery(jpql);
        //对占位符赋值,从1开始
        query.setParameter(1, "余不%");
        //查询并得到返回结果
        Customer customer = (Customer) query.getSingleResult();
        System.out.println(customer.getCustName());
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
    } finally {
        em.close();
    }
}
  • 排序查询

@Test
public void testOrder() {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        // 创建query对象
        String jpql = "from Customer order by custId desc";
        Query query = em.createQuery(jpql);
        // 查询并得到返回结果
        List<Customer> list = query.getResultList(); // 得到集合返回类型
        for (Customer customer : list) {
            System.out.println(customer.getCustId() + " === " + customer.getCustName());
        }
        tx.commit();
    } catch (Exception e) {
        // 回滚事务
        tx.rollback();
        e.printStackTrace();
    } finally {
        // 释放资源
        em.close();
    }
}
  • 统计查询

@Test
public void findCount() {
    EntityManager em = null;
    EntityTransaction tx = null;
    try {
        em = JPAUtil.getEntityManager();
        tx = em.getTransaction();
        tx.begin();
        // 查询全部客户
        // 1.创建query对象
        String jpql = "select count(custId) from Customer";
        Query query = em.createQuery(jpql);
        // 2.查询并得到返回结果
        Object count = query.getSingleResult();
        System.out.println(count);
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        e.printStackTrace();
    } finally {
        em.close();
    }
}


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马