jpa 订阅
JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 [1]  Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一。 展开全文
JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 [1]  Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一。
信息
外文名
Java Persistence API
领    域
IT,编程
类    别
专业术语
中文名
Java 持久层 API
语    言
Java
JPA起源
JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它又不限于EJB 3.0,你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范,由此可见,经过这几年的实践探索,能够脱离容器独立运行,方便开发和测试的理念已经深入人心了。Hibernate3.2+、TopLink 10.1.3以及OpenJPA都提供了JPA的实现。JPA的总体思想和现有Hibernate、TopLink、JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:ORM映射元数据JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;API用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。查询语言这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
收起全文
精华内容
参与话题
问答
  • spring boot 中使用 jpa以及jpa介绍

    万次阅读 多人点赞 2017-12-13 10:34:24
    最近在项目中使用了一下jpa,发现还是挺好用的。这里就来讲一下jpa以及在spring boot中的使用。 在这里我们先来了解一下jpa。1.什么是jpa呢?JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述...

    最近在项目中使用了一下jpa,发现还是挺好用的。这里就来讲一下jpa以及在spring boot中的使用。
    在这里我们先来了解一下jpa。

    1.什么是jpa呢?

    JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
    

    2.jpa具有什么优势?

    2.1标准化
    JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。
    2.2容器级特性的支持
    JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。
    2.3简单方便
    JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。
    2.4查询能力
    JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。
    2.4高级特性
    JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。
    

    3.基于注解的使用

    本篇只介绍注解的使用,另一种基于xml方式的使用大家有兴趣可以自行了解一下。

    3.1 JPA拥有哪些注解呢?

    注解 解释
    @Entity 声明类为实体或表。
    @Table 声明表名。
    @Basic 指定非约束明确的各个字段。
    @Embedded 指定类或它的值是一个可嵌入的类的实例的实体的属性。
    @Id 指定的类的属性,用于识别(一个表中的主键)。
    @GeneratedValue 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
    @Transient 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
    @Column 指定持久属性栏属性。
    @SequenceGenerator 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。
    @TableGenerator 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。
    @AccessType 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
    @JoinColumn 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
    @UniqueConstraint 指定的字段和用于主要或辅助表的唯一约束。
    @ColumnResult 参考使用select子句的SQL查询中的列名。
    @ManyToMany 定义了连接表之间的多对多一对多的关系。
    @ManyToOne 定义了连接表之间的多对一的关系。
    @OneToMany 定义了连接表之间存在一个一对多的关系。
    @OneToOne 定义了连接表之间有一个一对一的关系。
    @NamedQueries 指定命名查询的列表。
    @NamedQuery 指定使用静态名称的查询。

    了解了注解之后我们来看看如何使用吧

    4.代码实战

    4.1maven依赖

    添加jpa起步依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>

    4.2配置文件

    在application.yml文件中添加如下配置

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/mytest
        type: com.alibaba.druid.pool.DruidDataSource
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver //驱动
      jpa:
        hibernate:
          ddl-auto: update //自动更新
        show-sql: true  //日志中显示sql语句
    jpa.hibernate.ddl-auto是hibernate的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。该参数的几种配置如下:
        ·create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
        ·create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
        ·update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
        ·validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
    

    以上我们完成了基本的配置工作,记下来看一下如何进行表与实体的映射,以及数据访问接口。

    4.3创建实体以及数据访问接口

    首先来看一下实体类Person.java

    @Entity
    @Getter
    @Setter
    public class Person {
    
        @Id
        @GeneratedValue
        private Long id;
    
        @Column(name = "name", nullable = true, length = 20)
        private String name;
    
        @Column(name = "agee", nullable = true, length = 4)
        private int age;
    }

    接着是PersonRepository.java,改接口只需要继承JpaRepository接口即可。

    public interface PersonRepository extends JpaRepository<Person, Long> {
    }

    然后写一个rest接口以供测试使用。

    @RestController
    @RequestMapping(value = "person")
    public class PerconController {
    
        @Autowired
        private PersonRepository personRepository;
    
        @PostMapping(path = "addPerson")
        public void addPerson(Person person) {
            personRepository.save(person);
        }
    
        @DeleteMapping(path = "deletePerson")
        public void deletePerson(Long id) {
            personRepository.delete(id);
        }
    }

    好了,让我们来运行一下程序看看结果吧,启动程序,查询数据库我们就可以看到,JPA以及自动帮我们创建了表
    这里写图片描述

    接下来我们调用一下addPerson接口。我们使用postman来测试:
    这里写图片描述
    然后通过查询数据库来看一下结果:
    这里写图片描述
    我们可以看到成功插入了数据,并且观察表结构可以看到,agee是我们定义的column名称,id为自增。并且从上面的repository接口代码我们可以看到,接口中并没有定义任何的方法,这是因为JpaRepository中帮我们定义了基础的增删改查方法,可以很方便的直接使用。

    接下来我们来看一下如何编写自己的方法。我们以根据name查询person为例。添加一个rest接口

        @GET
        @Produces(TYPE_JSON)
        @Path("getPerson")
        public Object getPerson(@QueryParam("name") String name) {
            return personRepository.findByName(name);
        }

    并在repository接口中添加如下查询方法:

    Person findByName(String name);

    重启之后让我们来看一下查询结果

    这里写图片描述
    我们可以看到通过name获取到了想要的结果。我们也可以在日志中看到hibernate输出的日志:

    Hibernate: select person0_.id as id1_0_, person0_.agee as agee2_0_, person0_.name as name3_0_ from person person0_ where person0_.name=?
    

    那么JPA是通过什么规则来根据方法名生成sql语句查询的呢?
    其实JPA在这里遵循Convention over configuration(约定大约配置)的原则,遵循spring 以及JPQL定义的方法命名。Spring提供了一套可以通过命名规则进行查询构建的机制。这套机制会把方法名首先过滤一些关键字,比如 find…By, read…By, query…By, count…By 和 get…By 。系统会根据关键字将命名解析成2个子语句,第一个 By 是区分这两个子语句的关键词。这个 By 之前的子语句是查询子语句(指明返回要查询的对象),后面的部分是条件子语句。如果直接就是 findBy… 返回的就是定义Respository时指定的领域对象集合,同时JPQL中也定义了丰富的关键字:and、or、Between等等,下面我们来看一下JPQL中有哪些关键字:

    Keyword Sample JPQL snippet
    And findByLastnameAndFirstname … where x.lastname = ?1 and
    Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
    Is,Equals findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
    Between findByStartDateBetween … where x.startDate between ?1 and ?2
    LessThan findByAgeLessThan … where x.age < ?1
    LessThanEqual findByAgeLessThanEqual … where x.age ⇐ ?1
    GreaterThan findByAgeGreaterThan … where x.age > ?1
    GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
    After findByStartDateAfter … where x.startDate > ?1
    Before findByStartDateBefore … where x.startDate < ?1
    IsNull findByAgeIsNull … where x.age is null
    IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
    Like findByFirstnameLike … where x.firstname like ?1
    NotLike findByFirstnameNotLike … where x.firstname not like ?1
    StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
    EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
    Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
    OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
    Not findByLastnameNot … where x.lastname <> ?1
    In findByAgeIn(Collection ages) … where x.age in ?1
    NotIn findByAgeNotIn(Collection age) … where x.age not in ?1
    TRUE findByActiveTrue() … where x.active = true
    FALSE findByActiveFalse() … where x.active = false
    IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)
    ……

    以上就是jpa的简单实用和介绍。

    展开全文
  • JPA(一):十分钟入门 JPA

    千次阅读 2019-11-16 09:19:09
    版权声明:本文为CSDN博主「Mr丶sirius」的原创文章 ...一.JPA的概念 为了节省时间,更加具体的解释我们就略过吧。 二.在IDEA中使用JPA 2.1.添加JAP依赖 添加相关的maven依赖 <properties> <proj...

    一.JPA的概念

    在这里插入图片描述
    为了节省时间,更加具体的解释我们就略过吧。

    二.在IDEA中使用JPA

    2.1.添加JAP依赖

    添加相关的maven依赖

    <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.7</maven.compiler.source>
            <maven.compiler.target>1.7</maven.compiler.target>
            <hibernate.version>5.2.17.Final</hibernate.version>
            <goda.time.version>2.9.9</goda.time.version>
        </properties>
        <dependencies>
     
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
     
            <!-- jdbc驱动包  -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.37</version>
            </dependency>
     
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-core</artifactId>
                <version>4.3.10.Final</version>
            </dependency>
     
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>4.3.10.Final</version>
            </dependency>
     
            <dependency>
                <groupId>org.hibernate.javax.persistence</groupId>
                <artifactId>hibernate-jpa-2.1-api</artifactId>
                <version>1.0.0.Final</version>
            </dependency>
     
            <dependency>
                <groupId>org.hibernate.common</groupId>
                <artifactId>hibernate-commons-annotations</artifactId>
                <version>4.0.5.Final</version>
            </dependency>
     
            <!--持久化依赖-->
            <dependency>
                <groupId>joda-time</groupId>
                <artifactId>joda-time</artifactId>
                <version>${goda.time.version}</version>
            </dependency>
     
            <dependency>
                <groupId>org.jadira.usertype</groupId>
                <artifactId>usertype.core</artifactId>
                <version>6.0.1.GA</version>
            </dependency>
     
            <dependency>
                <groupId>antlr</groupId>
                <artifactId>antlr</artifactId>
                <version>2.7.7</version>
            </dependency>
     
            <dependency>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>1.6.1</version>
            </dependency>
     
            <dependency>
                <groupId>org.jboss</groupId>
                <artifactId>jandex</artifactId>
                <version>1.1.0.Final</version>
            </dependency>
     
            <dependency>
                <groupId>org.javassist</groupId>
                <artifactId>javassist</artifactId>
                <version>3.18.1-GA</version>
            </dependency>
     
            <dependency>
                <groupId>org.jboss.logging</groupId>
                <artifactId>jboss-logging</artifactId>
                <version>3.1.4.GA</version>
            </dependency>
     
            <dependency>
                <groupId>org.jboss.logging</groupId>
                <artifactId>jboss-logging-annotations</artifactId>
                <version>1.2.0.Beta1</version>
                <scope>provided</scope>
            </dependency>
     
            <dependency>
                <groupId>org.jboss.spec.javax.transaction</groupId>
                <artifactId>jboss-transaction-api_1.1_spec</artifactId>
                <version>1.0.0.Final</version>
            </dependency>
     
            <dependency>
                <groupId>javax.ejb</groupId>
                <artifactId>ejb-api</artifactId>
                <version>3.0</version>
            </dependency>
     
        </dependencies>
    

    2.2.配置JPA运行环境

    在IDEA中,resources文件夹下,也就是资源文件夹下,创建META-INF文件夹,在该文件夹下创建persistence.xml文件,添加以下配置。

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.1"
                 xmlns="http://xmlns.jcp.org/xml/ns/persistence"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
                 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
     
        <persistence-unit name="MyJPA" transaction-type="RESOURCE_LOCAL">
            <properties>
                <property name="javax.persistence.jdbc.driver"
                          value="com.mysql.jdbc.Driver" />
                <property name="javax.persistence.jdbc.url"
                          value="jdbc:mysql://localhost:3306/jpa" />
                <property name="javax.persistence.jdbc.user" value="root" />
                <property name="javax.persistence.jdbc.password" value="root" />
                <property name="hibernate.dialect"
                          value="org.hibernate.dialect.MySQL5Dialect" />
                <property name="hibernate.show_sql" value="true" />
                <property name="hibernate.hbm2ddl.auto" value="update" />
            </properties>
     
        </persistence-unit>
     
    </persistence>
    

    如下:
    在这里插入图片描述

    2.3.创建表

    CREATE TABLE `user` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `name` varchar(255) DEFAULT NULL,
        `password` varchar(255) DEFAULT NULL,
       PRIMARY KEY (`id`)
       ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    

    2.4.在IDEA中配置数据源

    在IDEA的右边有Database,按以下步骤操作即可。

    这里也可以不配置,配置之后,可以在IDEA中直接看到数据库中的表,并且之后再IDEA中写的代码也不用有警告。
    在这里插入图片描述
    添加你的数据库名字,第一次配置下边会提示你下载插件,很具提示即可。
    在这里插入图片描述

    2.5.测试
    创建User类

    package com.hly.jpa.model.oneToOne;
     
    import javax.persistence.*;
    /**
     * @author :hly
     * @github :github.com/SiriusHly
     * @blog :blog.csdn.net/Sirius_hly
     * @date :2018/9/27
     */
    @Entity
    //指定表名,指定唯一约束
    @Table(name = "user",uniqueConstraints = {@UniqueConstraint(columnNames = {"id","name"})})
    public class User {
        @Id//指定主键
        @GeneratedValue
        private int id;
        @Column
        private String name;
        @Column
        private String password;
     
        //一对一映射
        @OneToOne(optional = true, cascade = CascadeType.ALL)
        @JoinColumn(name = "articleId", unique = true)
        public Article article;
     
        //省略了getter和setter
    }
    
     /**
         * 获取应用管理的EntityManager
         */
        @Test
        public void testApplicationEntityManager() {
            EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("MyJPA");
            EntityManager em = entityManagerFactory.createEntityManager();
            em.getTransaction().begin();
            User user = new User();
            user.setName("hly");
            //以上两行为新建状态
            //托管状态
            em.persist(user);
            //事务提交或调用flush()方法后会同步到数据库
            em.getTransaction().commit();
            //根据主键获取对象
            //System.err.println(em.find(User.class,1));
            //System.err.println(em.getReference(User.class,1));
            em.close();
            entityManagerFactory.close();
        }
    

    数据库中插入数据则成功。

    2.6.EntityManager接口
    在这里插入图片描述
    在这里插入图片描述

    2.7.实体类中注解的含义

    在这里插入图片描述

    2.8.代码及地址思维导图

    完整代码在笔者的github,欢迎访问。

    展开全文
  • JPA - jpa简介

    千次阅读 2018-12-01 21:56:51
    JPA是什么? JPA:Java Persistence API:用于对象持久化 API Java EE5.0平台标准的ORM规范,使得应用程序以统一的方式访问持久层 Java应用程序根据每个持久化框架的调用方式不同,需要写不同的调用实现。 而JPA...

    JPA是什么?
    JPA:Java Persistence API:用于对象持久化 API
    Java EE5.0平台标准的ORM规范,使得应用程序以统一的方式访问持久层

    Java应用程序根据每个持久化框架的调用方式不同,需要写不同的调用实现。
    而JPA可以做到 Java应用程序只需要遵守JPA规范就可以实现与各个持久层框架的结合使用而该规范的具体实现交由各个ORM框架提供,并不需要根据不同的框架写不同的实现。面向JPA编程即可。

    结论:使得应用程序以统一的方式访问持久层。

    目前实现JPA规范的ORM框架有 Hibernate(推荐使用)、OpenJPA、TopLink,后面两种没用过。

    放两张图片感受下JPA在应用程序中所起到的作用。

    应用程序Application在jdbc规范未出现之前直接访问数据库,那么根据数据库的不同就需要有不同的访问方式,jdbc规范出现之后,应用程序通过实现jdbc规范来访问不同的数据库,不用考虑数据库的不同。因为各个数据库厂商也实现了jdbc规范

    目前市面上有很多开源的ORM框架,但是每个框架的使用方式不同,即应用程序还是需要根基orm框架来集成使用它,JPA的出现改变了这一现状。应用程序只需要实现JPA即可

     JDBC的作用是统一对接数据库的标准,JPA所起的作用是统一对接ORM持久层框架的标准 。

    声明:以上博文内容整理自S硅谷JPA教程,非常感谢!

    展开全文
  • jpa的使用和详解

    万次阅读 2017-11-20 09:39:40
    最近在公司频繁地使用jpa ,也阅读很多更大网站的文章,现在我把阅读过的文章总结成一篇 Bean Validation是JavaEE6数据验证新框架,ValidationAPI并不依赖特定的应用层或是编程模型,这样同一套验证可由应用的所有层...

    最近在公司频繁地使用jpa ,也阅读很多更大网站的文章,现在我把阅读过的文章总结成一篇

    Bean Validation是JavaEE6数据验证新框架,ValidationAPI并不依赖特定的应用层或是编程模型,这样同一套验证可由应用的所有层共享.它还提供了通过扩展ValidationAPI来增加客户化验证约束的机制以及查询约束元数据仓库的手段. 

      在Java EE6的BeanValidation出现之前,开发者不得不在表示层框架、业务层以及持久层中编写验证规则以保证这些规则的同步性,但这么做非常浪费时间而且极易出错.BeanValidation是通过约束实现的,这些约束以注解的形式出现,注解可以放在JavaBean(如backingbean)的属性、方法或是类上面.约束既可以是内建的注解(位于javax.validation.constraints包下面),也可以由用户定义。一些常用的内建注解列举如下: 

       ◆Min:被@Min所注解的元素必须是个数字,其值要大于或等于给定的最小值。
      ◆Max:被@Max所注解的元素必须是个数字,其值要小于或等于给定的最大值。 
      ◆Size:@Size表示被注解的元素必须位于给定的最小值和最大值之间。支持Size验证的数据类型有String、Collection(计算集合的大小)、Map以及数组。 
      ◆NotNull:@NotNull确保被注解的元素不能为null。 
      ◆Null:@Null确保被注解的元素一定为null。 
      ◆Pattern:@Pattern确保被注解的元素(String)一定会匹配给定的Java正则表达式。  

    Hibernate4之JPA规范配置详解

    @Table 

    Table用来定义entity主表的name,catalog,schema等属性。 
    属性说明: 
    • name:表名
    • catalog:对应关系数据库中的catalog
    • schema:对应关系数据库中的schema
    • UniqueConstraints:定义一个UniqueConstraint数组,指定需要建唯一约束的列.UniqueConstraint定义在Table或SecondaryTable元数据里,用来指定建表时需要建唯一约束的列。下面是指定2个字段要唯一约束.
    Example:
        @Entity
        @Table(
            name="EMPLOYEE",
            uniqueConstraints=
                @UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})
        )
        public class Employee { ... }

    @ID 和 @GeneratedValue

    通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 
    其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法, 
    JPA提供四种标准用法,由@GeneratedValue的源代码可以明显看出.

    @Target({METHOD, FIELD})
    @Retention(RUNTIME)
    
    public @interface GeneratedValue {
    
        GenerationType strategy() default AUTO;
    
        String generator() default "";
    }
    其中GenerationType: 
    package javax.persistence;
    
    public enum GenerationType {
    
        TABLE,
    
        SEQUENCE,
    
        IDENTITY,
    
        AUTO
    }
    JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO. 
    • TABLE:使用一个特定的数据库表格来保存主键。 
    • SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。 
    • IDENTITY:主键由数据库自动生成(主要是自动增长型) 
    • AUTO:主键由程序控制(也是默认的,在指定主键时,如果不指定主键生成策略,默认为AUTO)
    @Id
        @GeneratedValue
        private Long id;

    四种数据库的支持情况如下:

    数据库名称

    支持的id策略

    mysql

    GenerationType.TABLE
    GenerationType.AUTO
    GenerationType.IDENTITY
    不支持GenerationType.SEQUENCE

    oracle

    strategy=GenerationType.AUTO
    GenerationType.SEQUENCE
    GenerationType.TABLE
    不支持GenerationType.IDENTITY

    postgreSQL

    GenerationType.TABLE
    GenerationType.AUTO
    GenerationType.IDENTITY
    GenerationType.SEQUENCE
    都支持

    kingbase

    GenerationType.TABLE
    GenerationType.SEQUENCE
    GenerationType.IDENTITY
    GenerationType.AUTO
    都支持

    @GeneratedValue:主键的产生策略,通过strategy属性指定。

      主键产生策略通过GenerationType来指定。GenerationType是一个枚举,它定义了主键产生策略的类型。

      1、AUTO 自动选择一个最适合底层数据库的主键生成策略。如MySQL会自动对应auto increment。这个是默认选项,即如果只写@GeneratedValue,等价于@GeneratedValue(strategy=GenerationType.AUTO)。

      2、IDENTITY 表自增长字段,Oracle不支持这种方式。

      3、SEQUENCE 通过序列产生主键,MySQL不支持这种方式。

      4、TABLE 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。不同的JPA实现商生成的表名是不同的,如 OpenJPA生成openjpa_sequence_table表,Hibernate生成一个hibernate_sequences表,而TopLink则生成sequence表。这些表都具有一个序列名和对应值两个字段,如SEQ_NAME和SEQ_COUNT。

      在我们的应用中,一般选用@GeneratedValue(strategy=GenerationType.AUTO)这种方式,自动选择主键生成策略,以适应不同的数据库移植。

      如果使用Hibernate对JPA的实现,可以使用Hibernate对主键生成策略的扩展,通过Hibernate的@GenericGenerator实现。

      @GenericGenerator(name = "system-uuid", strategy = "uuid") 声明一个策略通用生成器,name为"system-uuid",策略strategy为"uuid"。

      @GeneratedValue(generator = "system-uuid") 用generator属性指定要使用的策略生成器。

      这是我在项目中使用的一种方式,生成32位的字符串,是唯一的值。最通用的,适用于所有数据库。



    构建CriteriaQuery 实例API说明

    1.CriteriaBuilder 安全查询创建工厂,创建CriteriaQuery,创建查询具体具体条件Predicate 等

    CriteriaBuilder是一个工厂对象,安全查询的开始.用于构建JPA安全查询.可以从EntityManager 或 EntityManagerFactory类中获得CriteriaBuilder.
    比如: CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

    2.CriteriaQuery 安全查询主语句

    CriteriaQuery对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。
    它通过调用 CriteriaBuilder, createQuery 或CriteriaBuilder.createTupleQuery 获得。
    CriteriaBuilder就像CriteriaQuery 的工厂一样。
    CriteriaBuilder工厂类是调用EntityManager.getCriteriaBuilder 或 EntityManagerFactory.getCriteriaBuilder而得。 
    Employee实体的 CriteriaQuery 对象以下面的方式创建:

    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);

    3.Root 定义查询的From子句中能出现的类型

    AbstractQuery是CriteriaQuery 接口的父类。它提供得到查询根的方法。
    Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似。
    Root实例也是类型化的,且定义了查询的FROM子句中能够出现的类型。
    查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。
    Criteria查询,可以有多个查询根。
    Employee实体的查询根对象可以用以下的语法获得 : 
    Root<Employee> employee = criteriaQuery.from(Employee.class);

    4.Predicate 过滤条件

    过滤条件应用到SQL语句的FROM子句中。
    在criteria 查询中,查询条件通过Predicate 或Expression 实例应用到CriteriaQuery 对象上。
    这些条件使用 CriteriaQuery .where 方法应用到CriteriaQuery 对象上。
    CriteriaBuilder 也是作为Predicate 实例的工厂,Predicate 对象通过调用CriteriaBuilder 的条件方法( equal,notEqual, gt, ge,lt, le,between,like等)创建。
    Predicate 实例也可以用Expression 实例的 isNull, isNotNull 和 in方法获得,复合的Predicate 语句可以使用CriteriaBuilder的and, or andnot 方法构建。
    下面的代码片段展示了Predicate 实例检查年龄大于24岁的员工实例:
    Predicate condition = criteriaBuilder.gt(employee.get(Employee_.age), 24);
    criteriaQuery.where(condition);

    过Employee_元模型类age属性,称之为路径表达式。若age属性与String文本比较,编译器会抛出错误,这在JPQL中是不可能的。

    5.Predicate[] 多个过滤条件

    List<Predicate> predicatesList = new ArrayList<Predicate>();

    predicatesList.add(.....Pridicate....)

    criteriaQuery.where(predicatesList.toArray(new Predicate[predicatesList.size()]));

    OR语句


    predicatesList.add(criteriaBuilder.or(criteriaBuilder.equal(root.get(RepairOrder_.localRepairStatus), LocalRepairStatus.repairing),criteriaBuilder.equal(root.get(RepairOrder_.localRepairStatus), LocalRepairStatus.diagnos)));


    忽略大小写(全大写)


    predicatesList.add(criteriaBuilder.like(criteriaBuilder.upper(root.get(RepairShop_.shopName)), StringUtils.upperCase(StringUtils.trim(this.shopName)) + "%"));
    通过如上两句添加多个.


    6.TypedQuery执行查询与获取元模型实例

    注意,你使用EntityManager创建查询时,可以在输入中指定一个CriteriaQuery对象,它返回一个TypedQuery,它是JPA 2.0引入javax.persistence.Query接口的一个扩展,TypedQuery接口知道它返回的类型。

    所以使用中,先创建查询得到TypedQuery,然后通过typeQuery得到结果.

    当EntityManager.createQuery(CriteriaQuery)方法调用时,一个可执行的查询实例会创建,该方法返回指定从 criteria 查询返回的实际类型的TypedQuery 对象。

    TypedQuery 接口是javax.persistence.Queryinterface.的子类型。在该片段中, TypedQuery 中指定的类型信息是Employee,调用getResultList时,查询就会得到执行 
    TypedQuery<Employee> typedQuery = em.createQuery(criteriaQuery);
    List<Employee> result = typedQuery.getResultList();

    元模型实例通过调用 EntityManager.getMetamodel 方法获得,EntityType<Employee>的元模型实例通过调用Metamodel.entity(Employee.class)而获得,其被传入 CriteriaQuery.from 获得查询根。

    Metamodel metamodel = em.getMetamodel();EntityType<Employee> 
    Employee_ = metamodel.entity(Employee.class);
    Root<Employee> empRoot = criteriaQuery.from(Employee_);

    也有可能调用Root.getModel方法获得元模型信息。类型 EntityType<Dept>的实例Dept_和name属性可以调用getSingularAttribute 方法获得,它与String文本进行比较:

    CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
    Root<Dept> dept = criteriaQuery.from(Dept.class);
    EntityType<Dept> Dept_ = dept.getModel();
    Predicate testCondition = criteriaBuilder.equal(dept.get(Dept_.getSingularAttribute("name", String.class)), "Ecomm");

    7.Expression 用在查询语句的select,where和having子句中,该接口有 isNull, isNotNull 和 in方法

    Expression对象用在查询语句的select,where和having子句中,该接口有 isNull, isNotNull 和 in方法,下面的代码片段展示了Expression.in的用法,employye的年龄检查在20或24的。
    CriteriaQuery<Employee> criteriaQuery = criteriaBuilder .createQuery(Employee.class);
    Root<Employee> employee = criteriaQuery.from(Employee.class);
    criteriaQuery.where(employee.get(Employee_.age).in(20, 24));
    em.createQuery(criteriaQuery).getResultList();

    对应的SQL: SELECT * FROM employee WHERE age in (20, 24)

    下面也是一个更贴切的例子:

    //定义一个Expression
    Expression<String> exp = root.get(Employee.id);
    //
    List<String> strList=new ArrayList<>();	
    strList.add("20");
    strList.add("24");		
    predicatesList.add(exp.in(strList));
    
    criteriaQuery.where(predicatesList.toArray(new Predicate[predicatesList.size()]));

    8.复合谓词

    Criteria Query也允许开发者编写复合谓词,通过该查询可以为多条件测试下面的查询检查两个条件。首先,name属性是否以M开头,其次,employee的age属性是否是25。逻辑操作符and执行获得结果记录。
    criteriaQuery.where(
     criteriaBuilder.and(
      criteriaBuilder.like(employee.get(Employee_.name), "M%"), 
      criteriaBuilder.equal(employee.get(Employee_.age), 25)
    ));
    em.createQuery(criteriaQuery).getResultList();

    连接查询

    在SQL中,连接跨多张表以获取查询结果,类似的实体连接通过调用 From.join 执行,连接帮助从一个实体导航到另一个实体以获得查询结果。
    Root的join方法返回一个 Join<Dept, Employee>类型(也可以是SetJoin,,ListJoin,MapJoin 或者 CollectionJoin类型)。

    默认情况下,连接操作使用内连接,而外连接可以通过在join方法中指定JoinType参数为LEFT或RIGHT来实现。

    CriteriaQuery<Dept> cqDept = criteriaBuilder.createQuery(Dept.class);
    Root<Dept> deptRoot = cqDept.from(Dept.class);
    Join<Dept, Employee> employeeJoin = deptRoot.join(Dept_.employeeCollection);
    cqDept.where(criteriaBuilder.equal(employeeJoin.get(Employee_.deptId).get(Dept_.id), 1));
    TypedQuery<Dept> resultDept = em.createQuery(cqDept);

    抓取连接

    当涉及到collection属性时,抓取连接对优化数据访问是非常有帮助的。这是通过预抓取关联对象和减少懒加载开销而达到的。
    使用 criteria 查询,fetch方法用于指定关联属性
    Fetch连接的语义与Join是一样的,因为Fetch操作不返回Path对象,所以它不能将来在查询中引用。
    在以下例子中,查询Dept对象时employeeCollection对象被加载,这不会有第二次查询数据库,因为有懒加载。
    CriteriaQuery<Dept> d = cb.createQuery(Dept.class);
    Root<Dept> deptRoot = d.from(Dept.class);
    deptRoot.fetch("employeeCollection", JoinType.LEFT);
    d.select(deptRoot);
    List<Dept> dList = em.createQuery(d).getResultList();

    对应SQL: SELECT * FROM dept d, employee e  WHERE d.id = e.deptId

    路径表达式

    Root实例,Join实例或者从另一个Path对象的get方法获得的对象使用get方法可以得到Path对象,当查询需要导航到实体的属性时,路径表达式是必要的。
    Get方法接收的参数是在实体元模型类中指定的属性。
    Path对象一般用于Criteria查询对象的select或where方法。例子如下:
    CriteriaQuery<String> criteriaQuery = criteriaBuilder.createQuery(String.class);
    Root<Dept> root = criteriaQuery.from(Dept.class);
    criteriaQuery.select(root.get(Dept_.name));&nbsp;

    参数化表达式

         在JPQL中,查询参数是在运行时通过使用命名参数语法(冒号加变量,如 :age)传入的。在Criteria查询中,查询参数是在运行时创建ParameterExpression对象并为在查询前调用TypeQuery,setParameter方法设置而传入的。下面代码片段展示了类型为Integer的ParameterExpression age,它被设置为24:
    ParameterExpression<Integer> age = criteriaBuilder.parameter(Integer.class);
    Predicate condition = criteriaBuilder.gt(testEmp.get(Employee_.age), age);
    criteriaQuery.where(condition);
    TypedQuery<Employee> testQuery = em.createQuery(criteriaQuery);
    List<Employee> result = testQuery.setParameter(age, 24).getResultList();
    Corresponding SQL: SELECT * FROM Employee WHERE age = 24;

    排序结果

         Criteria查询的结果能调用CriteriaQuery.orderBy方法排序,该方法接收一个Order对象做为参数。通过调用  CriteriaBuilder.asc 或 CriteriaBuilder.Desc,Order对象能被创建。以下代码片段中,Employee实例是基于age的升序排列。 
    CriteriaQuery<Employee> criteriaQuery = criteriaBuilder .createQuery(Employee.class);
     Root<Employee> employee = criteriaQuery.from(Employee.class);
     criteriaQuery.orderBy(criteriaBuilder.asc(employee.get(Employee_.age)));
      em.createQuery(criteriaQuery).getResultList();
     对应 SQL: SELECT * FROM Employee ORDER BY age ASC

    分组

    CriteriaQuery 实例的groupBy 方法用于基于Expression的结果分组。查询通过设置额外表达式,以后调用having方法。下面代码片段中,查询按照Employee类的name属性分组,且结果以字母N开头:
    CriteriaQuery<Tuple> cq = criteriaBuilder.createQuery(Tuple.class);
    Root<Employee> employee = cq.from(Employee.class);
      cq.groupBy(employee.get(Employee_.name));
      cq.having(criteriaBuilder.like(employee.get(Employee_.name), "N%"));
    cq.select(criteriaBuilder.tuple(employee.get(Employee_.name),criteriaBuilder.count(employee)));
      TypedQuery<Tuple> q = em.createQuery(cq);
      List<Tuple> result = q.getResultList();
    对应 SQL:    SELECT name, COUNT(*) FROM employeeGROUP BY name HAVING name like 'N%'

    查询投影

    Criteria查询的结果与在Critiria查询创建中指定的一样。结果也能通过把查询根传入 CriteriaQuery.select中显式指定。Criteria查询也给开发者投影各种结果的能力。

    使用construct()

    使用该方法,查询结果能由非实体类型组成。在下面的代码片段中,为EmployeeDetail类创建了一个Criteria查询对象,而EmployeeDetail类并不是实体类型。
    CriteriaQuery<EmployeeDetails> criteriaQuery = criteriaBuilder.createQuery(EmployeeDetails.class);
      Root<Employee> employee = criteriaQuery.from(Employee.class);
      criteriaQuery.select(criteriaBuilder.construct(EmployeeDetails.class, employee.get(Employee_.name), employee.get(Employee_.age)));
      em.createQuery(criteriaQuery).getResultList();
      Corresponding SQL: SELECT name, age FROM employee<span style="white-space: normal;">&nbsp;</span>

    返回Object[]的查询

    Criteria查询也能通过设置值给CriteriaBuilder.array方法返回Object[]的结果。下面的代码片段中,数组大小是2(由String和Integer组成)。
    CriteriaQuery<Object[]> criteriaQuery = criteriaBuilder.createQuery(Object[].class);
      Root<Employee> employee = criteriaQuery.from(Employee.class);
      criteriaQuery.select(criteriaBuilder.array(employee.get(Employee_.name), employee.get(Employee_.age)));
      em.createQuery(criteriaQuery).getResultList();
    对应 SQL: SELECT name, age FROM employee

    返回元组(Tuple)的查询

    数据库中的一行数据或单个记录通常称为元组。通过调用CriteriaBuilder.createTupleQuery()方法,查询可以用于元组上。CriteriaQuery.multiselect方法传入参数,它必须在查询中返回。
    CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery();
       Root<Employee> employee = criteriaQuery.from(Employee.class);
       criteriaQuery.multiselect(employee.get(Employee_.name).alias("name"), employee.get(Employee_.age).alias("age"));
       em.createQuery(criteriaQuery).getResultList();
    对应 SQL: SELECT name, age FROM employee

    jpa的hql查询

    JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。
     
    JPQL就是一种查询语言,具有与 SQL 相类似的特征, JPQL 是完全面向对象的,具备继承、多态和关联等特性,和hibernate HQL很相似。
     
    查询语句的参数
    JPQL 语句支持两种方式的参数定义方式:命名参数和位置参数。在同一个查询语句中只允许使用一种参数定义方式。
     
    命令参数的格式为:“ : + 参数名”
    例:Query query = em.createQuery("select p from Person p where p.personid=:Id");
    query.setParameter("Id",new Integer(1));
    位置参数的格式为“ ?+ 位置编号”
    例:
    Query query = em.createQuery("select p from Person p where p.personid=?1");
    query.setParameter(1,new Integer(1));
     如果你需要传递 java.util.Date java.util.Calendar 参数进一个参数查询 你需要使用一个特殊的 setParameter()方法,相关的setParameter方法定义如下
     
    public interface Query
    {
    // 命名参数查询时使用,参数类型为 java.util.Date
    Query setParameter(String name, java.util.Date value, TemporalType temporalType);
    // 命名参数查询时使用,参数类型为 java.util.Calendar
    Query setParameter(String name, Calendar value, TemporalType temporalType);
    // 位置参数查询时使用,参数类型为 java.util.Date
    Query setParameter(int position, Date value, TemporalType temporalType);
    // 位置参数查询时使用,参数类型为 java.util.Calendar
    Query setParameter(int position, Calendar value, TemporalType temporalType);
    }
     
    因为一个 Date Calendar 对象能够描述一个真实的日期、时间或时间戳.所以我们需要告诉Query对象怎么使用这些参数,我们javax.persistence.TemporalType作为参数传递进 setParameter 方法,告诉查询接口在转换 java.util.Date java.util.Calendar 参数到本地 SQL 时使用什么数据库类型
     
    下面通过实例来学习JPQL语句,例子的entity Bean Person, Order, OrderItem他们之间的关系是:一个Person有多个Order,一个 Order 有多个 OrderItem
     
    JPQL语句的大小写敏感性:除了 Java 类和属性名称外,查询都是大小写不敏感的 。所以, SeLeCT sELEct 以及 SELECT 相同的,但是 com.foshanshop.ejb3.bean.Person com.foshanshop.ejb3.bean.PERSon 是不同的, person.name person.NAME也是不同的。
     
     
    命名查询
    可以在实体 bean 通过 @NamedQuery or@NamedQueries预先定义一个或多个查询语句,减少每次因书写错误而引起的BUG。通常把经常使用的查询语句定义成命名查询
     
    定义单个命名查询:
    @NamedQuery (name= "getPerson" , query= "FROM Person WHERE personid=?1")
    @Entity
    public class Person implements Serializable{
     
    如果要定义多个命名查询,应在 @javax.persistence.NamedQueries里定义@NamedQuery
    @NamedQueries ({
    @NamedQuery(name="getPerson", query="FROM Person WHERE personid=?1"),
    @NamedQuery(name="getPersonList", query="FROM Person WHERE age>?1" )
    })
    @Entity
    public class Person implements Serializable{
     
    当命名查询定义好了之后,我们就可以通过名称执行其查询。代码如下:
    Query query = em . createNamedQuery("getPerson");
    query.setParameter(1, 1);
     
     
    排序 (order by)
    "ASC" "DESC" 分别为升序和降序, JPQL 中默认为 asc 升序
    例:
    // 先按年龄降序排序,然后按出生日期升序排序
    Query query = em.createQuery("select p from Person porder by p.age desc, p.birthday asc ");
     
    查询部分属性
    通常来说,都是针对 Entity类的查询,返回的也是被查询的Entity类的实体。JP QL 也允许我们直接查询返回我们需要的属性,而不是返回整个Entity在一些Entity中属性特别多的情况,这样的查询可以提高性能
    例:
    // 查询我们感兴趣的属性 ( )
    Query query=em.createQuery("select p.personid, p.name from Person p order by p.personid desc ");
    // 集合中的元素不再是 Person, 而是一个 Object[] 对象数组
    List result = query.getResultList();
    if (result!=null){
    Iterator iterator = result.iterator();
    while( iterator.hasNext() ){
    Object[] row = ( Object[]) iterator.next();
    int personid = Integer.parseInt(row[0].toString());
    String PersonName = row[1].toString();
    。。。。
    }
    }
     
    查询中使用构造器 (Constructor)
    JPQL 支持将查询的属性结果直接作为一个 java class 的构造器参数,并产生实体作为结果返回 例如上面的例子只获取 person entity bean的name and personid属性,我们不希望返回的集合的元素是object[],而希望用一个类来包装它。就要用到使用构造器
    例:
    public class SimplePerson {
     private Integer personid;
    privateStringname;
       。。。。
    public SimplePerson() {
    }
    public SimplePerson(Integer personid, String name) {
    this . name = name;
    this . personid = personid;
    }
    }
     
    查询代码为:
    // 我们把需要的两个属性作为 SimplePerson 的构造器参数,并使用 new 函数。
    Query query = em.createQuery(" select new com.foshanshop.ejb3.bean.SimplePerson(p. personid, p.name) from Person p order by p.personid desc");
    // 集合中的元素是 SimplePerson 对象
    List result = query.getResultList();
    if (result!=null){
    Iterator iterator = result.iterator();
    while( iterator.hasNext() ){
    SimplePerson simpleperson = (SimplePerson) iterator.next();
    。。。。
    }
    }
     
    聚合查询 (Aggregation)
    JPQL 支持的聚合函数 包括:
    1. AVG()
    2. SUM()
    3. COUNT() 返回类型为 Long ,注意 count(*) 语法在 hibernate 中可用,但在 toplink 其它产品中并不可用
    4. MAX()
    5. MIN()
     
    例:
    // 获取最大年龄
    Query query = em.createQuery("selectmax(p.age)from Person p");
    Object result = query.getSingleResult();
    String maxAge = result.toString();
    // 获取平均年龄
    query = em.createQuery("select avg(p.age) from Person p");
    // 获取最小年龄
    query = em.createQuery("select min(p.age) from Person p");
    // 获取总人数
    query = em.createQuery("select count(p) from Person p");
    // 获取年龄总和
    query = em.createQuery("select sum(p.age) from Person p");
     
    如果聚合函数不是 select...from 的唯一一个返回列,需要使用 "GROUP BY" 语句 "GROUP BY" 应该包含select语句中除了聚合函数外的所有属性。
    例:
    // 返回男女生各自的总人数
    Query query = em.createQuery(" select p.sex, count(p) from Person p group by p.sex ");
    // 集合中的元素不再是 Person, 而是一个 Object[] 对象数组
    List result = query.getResultList();
     
    如果还需要加上查询条件,需要使用 "HAVING" 条件语句而不是 "WHERE" 语句
    例:
    // 返回人数超过 1 人的性别
    Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex having count(*)>?1");
    // 设置查询中的参数
    query.setParameter(1, new Long(1));
    // 集合中的元素不再是 Person, 而是一个 Object[] 对象数组
    List result = query.getResultList();
    关联 (join)
    JPQL 仍然支持和 SQL 中类似的关联语法:
    left out join/left join
    inner join
    left join fetch/inner join fetch
     
     
    left out join/left join 等,都是允许符合条件的右边表达式中的 Entiies为空(需要显式使用left join/left outer join的情况会比较少。
    例:
    // 获取 26 岁人的订单 , 不管 Order 中是否有 OrderItem
    select o from Order o left join o.orderItems where o.ower.age=26 order by o.orderid
     
     
    inner join 要求右边的表达式必须返回Entities
    例:
    // 获取 26 岁人的订单 ,Order 中必须要有 OrderItem
    select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid
     
     
    !!重要知识点 在默认的查询中,Entity中的集合属性默认不会被关联,集合属性默认是延迟加载( lazy-load )。那么,left fetch/left out fetch/inner join fetch提供了一种灵活的查询加载方式来提高查询的性能。
    例:
    private String QueryInnerJoinLazyLoad(){
    // 默认不关联集合属性变量 (orderItems) 对应的表
    Query query = em.createQuery("select o from Order oinner joino.orderItems where o.ower.age=26 order by o.orderid");
    List result = query.getResultList();
    if (result!=null && result.size()>0){
    // 这时获得 Order实体中orderItems(集合属性变量)为空
    Order order = (Order) result.get(0);
    // 当需要时, EJB3 Runtime才会执行一条SQL语句来加载属于当前Order
    //OrderItems
    Set<OrderItem> list =order.getOrderItems();
    Iterator<OrderItem> iterator = list.iterator();
    if (iterator.hasNext()){
    OrderItem orderItem =iterator.next();
    System.out.println ("订购产品名:"+ orderItem.getProductname());
    }
    }
     
    上面代码在执行 "select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid"时编译成的SQL如下(他不包含集合属性变量 (orderItems) 对应表的字段
    select order0_.orderid as orderid6_, order0_.amount as amount6_, order0_.person_id as
    person4_6_, order0_.createdate as createdate6_ from Orders order0_ inner join OrderItems
    orderitems1_ on order0_.orderid=orderitems1_.order_id, Person person2_ where
    order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid
     
     
    上面代码当执行到 Set<OrderItem> list = order.getOrderItems(); 才会执行一条 SQL 语句来加载属于当前OrderOrderItems ,编译成的 SQL 如下
    select orderitems0_.order_id as order4_1_, orderitems0_.id as id1_, orderitems0_.id as id7_0_,
    orderitems0_.order_id as order4_7_0_, orderitems0_.productname as productn2_7_0_,
    orderitems0_.price as price7_0_ from OrderItems orderitems0_ where orderitems0_.order_id=?
    order by orderitems0_.id ASC
     
    这样的查询性能上有不足的地方 。为了查询 N Order ,我们需要一条 SQL 语句获得所有的 Order 的原始对象属性,但需要另外N条语句获得每个OrderorderItems 集合属性。为了避免N+1的性能问题,我们可以利用join fetch一次过用一条SQL语句把Order的所有信息查询出来
     
    例子
    // 获取 26 岁人的订单 ,Order 中必须要有 OrderItem
    Query query = em.createQuery("select o from Order oinner join fetcho.orderItems where
    o.ower.age=26 order by o.orderid");
     
    上面这句HPQL编译成以下的 SQL
    select order0_.orderid as orderid18_0_, orderitems1_.id as id19_1_, order0_.amount as
    amount18_0_,order0_.person_id as person4_18_0_, order0_.createdate as createdate18_0_,
    orderitems1_.order_id as order4_19_1_, orderitems1_.productname as productn2_19_1_,
    orderitems1_.price as price19_1_, orderitems1_.order_id as order4_0__, orderitems1_.id as id0__
    from Orders order0_ inner join OrderItems orderitems1_ on
    order0_.orderid=orderitems1_.order_id, Person person2_ where
    order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid,
    orderitems1_.id ASC
     
    上面由于使用了 fetch,这个查询只会产生一条SQL语句,比原来需要N+1 SQL 语句在性能上有了极大的提升
     
     
    排除相同的记录 DISTINCT
    使用关联查询,我们很经常得到重复的对象,如下面语句:
    " select o from Order o inner join fetch o.orderItems order by o.orderid "
    当有 N orderItem 时就会产生 N Order, 而有些 Order 对象往往是相同的,这时我们需要使用DISTINCT关键字来排除掉相同的对象
    例:
    select DISTINCTo from Order o inner join fetch o.orderItems order by o.orderid
     
     
     
    比较 Entity
    在查询中使用参数查询时 ,参数类型除了 String, 原始数据类型 ( int, double)和它们的对象类型( Integer, Double), 可以是Entity的实例
    例:
    // 查询某人的所有订单
    Query query = em.createQuery("select o from Order o whereo.ower =?1order by o.orderid");
    Person person = new Person();
    person.setPersonid(new Integer(1));
    // 设置查询中的参数
    query.setParameter(1,person);
     
     
    批量更新 (Batch Update)
    HPQL支持批量更新
    例:
    // 把所有订单的金额加 10
    Query query = em.createQuery(" update Order as o set o.amount=o.amount+10 ");
    //update 的记录数
    int result = query. executeUpdate ();
     
     
    批量删除 (Batch Remove)
    例:
    // 把金额小于100的订单删除,先删除订单子项, 再删除订单
    Query query = em .createQuery( "delete from OrderItem item where item.order in(from Order as o where o.amount<100)");
    query. executeUpdate();
    query = em .createQuery( "delete from Order as o where o.amount<100" );
    query.executeUpdate(); //delete 的记录数
     
     
    使用操作符 NOT
    // 查询除了指定人之外的所有订单
    Query query = em.createQuery("select o from Order o wherenot(o.ower =?1)order by o.orderid");
    Person person = new Person();
    person.setPersonid(new Integer(2));
    // 设置查询中的参数
    query.setParameter(1,person);
     
     
    使用操作符 BETWEEN
    select o from Order as o where o.amount between 300 and 1000
     
    使用操作符 IN
    // 查找年龄为 26,21 Person
    select p from Person as p where p.age in(26,21)
     
    使用操作符 LIKE
    // 查找以字符串 "li" 开头的 Person
    select p from Person as p where p.name like 'li%'
     
    使用操作符 IS NULL
    // 查询含有购买者的所有 Order
    select o from Order as o where o.ower is [not] null
     
    使用操作符 IS EMPTY
    IS EMPTY 是针对集合属性 (Collection) 的操作符 。可以和 NOT 一起使用 注:低版权的 Mysql 不支持 IS EMPTY
    // 查询含有订单项的所有 Order
    select o from Order as o where o.orderItems is [not] empty
     
    使用操作符 EXISTS
    [NOT]EXISTS 需要和子查询配合使用。注:低版权的Mysql不支持EXISTS
    // 如果存在订单号为 1 的订单,就获取所有 OrderItem
    select oi from OrderItem as oi where exists (select o from Order o where o.orderid=1)
    // 如果不存在订单号为 10 的订单,就获取 id 1 OrderItem
    select oi from OrderItem as oi where oi.id=1 andnot exists(select o from Order o where o.orderid=10)
     
     
    字符串函数
    JPQL 定义了内置函数方便使用。这些函数的使用方法和SQL中相应的函数方法类似。包括:
    1. CONCAT 字符串拼接
    2. SUBSTRING 字符串截取
    3. TRIM 去掉空格
    4. LOWER 转换成小写
    5. UPPER 装换成大写
    6. LENGTH 字符串长度
    7. LOCATE 字符串定位
     
    例:
    // 查询所有人员,并在姓名后面加上字符串 "_foshan"
    select p.personid, concat(p.name, '_foshan') from Person as p
    // 查询所有人员 , 只取姓名的前三个字符
    select p.personid, substring (p.name,1,3) from Person as p
     
    计算函数
    HPQL 定义的计算函数包括:
    ABS 绝对值
    SQRT 平方根
    MOD 取余数
    SIZE 取集合的数量
     
    例:
    // 查询所有 Order 的订单号及其订单项的数量
    select o.orderid, size (o.orderItems) from Order as o group by o.orderid
    // 查询所有 Order 的订单号及其总金额 /10 的余数
    select o.orderid, mod (o.amount, 10) from Order as o
     
     
    子查询
    子查询可以用于 WHEREHAVING条件语句中
    例:
    // 查询年龄为 26 岁的购买者的所有 Order
    select o from Order as o where o.ower in(select p from Person as p where p.age =26)
     
     
    结果集分页
    有些时候当执行一个查询会返回成千上万条记录,事实上我们只需要显示一部分数据。这时我们需要对结果集进行分页 ,QueryAPI有两个接口方法可以解决这个问题:setMaxResults( )setFirstResult( )
     
    setMaxResults 方法设置获取多少条记录
    setFirstResult 方法设置从结果集中的那个索引开始获取 (假如返回的记录有 3 条,容器会自动为记录编上索引,索引从 0 开始,依次为 0 1 2
     
    例:
    public List getPersonList( int max, int whichpage) {
    try {
    int index = (whichpage-1) * max;
    Query query =em.createQuery("from Person p order by personid asc");
    List list = query.setMaxResults(max).
    setFirstResult(index).
    getResultList();
    em .clear(); // 分离内存中受EntityManager管理的实体bean,让VM进行垃圾回收
    return list;
    }

    jpa的sql查询



    展开全文
  • JPA详解

    2019-10-11 20:57:50
    JPA 的简介 Java Persistence API(Java 持久层 API):用于对象持久化的 API 作用:使得应用程序以统一的方式访问持久层 JPA 与 Hibernate的什么关系: ​ 1)JPA 是 一个标准的接口 ​ 2 Hibernate 是 JPA ...
  • JPA系列一:简介

    千次阅读 2019-05-02 11:47:37
    1、简介: Java Persistence API:用于对象持久化的 API。 Java EE 5.0 平台标准的 ORM 规范,... JPA 是规范:JPA 本质上就是一种 ORM 规范,不是ORM 框架 —— 因为 JPA 并未提供 ORM 实现,它只是制订了一些规范...
  • JPA 快速入门Demo

    2019-07-30 15:40:58
    1 JPA的优势 标准化 JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下...
  • JPA

    2020-04-14 11:05:56
    故事的主角 Jpa 1. JPA是什么 Java Persistence API:用于对象持久化的 API Java EE 5.0 平台标准的 ORM 规范,使得应用程序以统一的方式访问持久... JPA 是规范:JPA 本质上就是一种 ORM 规范,不是ORM 框架,...
  • 浅谈JPA一:JPA是什么?

    万次阅读 多人点赞 2018-10-27 01:02:18
    JPA 是一个基于O/R映射的标准规范(目前最新版本是JPA 2.1 )。所谓规范即只定义标准规则(如注解、接口),不提供实现,软件提供商可以按照标准规范来实现,而使用者只需按照规范中定义的方式来使用,而不用和软件...
  • 如何让jpa 持久化时不校验指定字段

    万次阅读 2018-05-08 15:10:24
    spring data jpa ,使用了validate校验,校验直接加在了于要持久化实体类上,为了方便简洁并没有使用DTO做验证,但是有的校验仅在Controller层需要校验,持久化时不需校验,因为我把他声明为@Transient的了,如下...
  • jpa连接数据库

    万次阅读 2017-05-15 16:23:28
    原文链接 1.XML配置 <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi=...xsi:schemaLocation="ht...
  • Spring Boot2.x: 集成JPA快速开发

    万次阅读 2020-05-21 23:28:08
    Spring Boot2.x集成JPA快速开发 什么是JPA 一种规范,并非ORM框架,也就是ORM上统一的规范 spring-boot-starter-data-jpa 是Spring Boot的项目,包含了spring-data-jpa和一些其他依赖用于Spring Boot项目 ...
  • springboot jpa 中使用逻辑删除

    万次阅读 2017-10-24 13:47:23
    1.indexs 指定索引@Index(columnList=""),@Index(columnList=""),可指定多个 ...3.@Where 指定调用jpa .. repository 查询时的条件 附:常用的jpql PS:唠唠嗑? 公众号搜索:DeanKano 企...
  • 为啥国人偏爱Mybatis,而老外喜欢Hibernate/JPA呢?

    万次阅读 多人点赞 2019-11-07 20:00:03
    声明:本文不会下关于Mybatis和JPA两个持久层框架哪个更好这样的结论。只是摆事实,讲道理,所以,请各位看官勿喷。 一、事件起因 关于Mybatis和JPA孰优孰劣的问题,争论已经很多年了。一直也没有结论,毕竟每个人...
  • SpringDataJpaJpaRepository增删改查

    万次阅读 多人点赞 2017-11-17 08:32:19
    Jpa查询 1. JpaRepository简单查询 基本查询也分为两种,一种是spring data默认已经实现,一种是根据查询的方法来自动解析成SQL。 预先生成方法 spring data jpa 默认预先生成了一些基本的CURD的方法,例如...
  • SpringBoot重点详解--使用JPA操作数据库

    万次阅读 多人点赞 2018-04-22 14:27:25
    目录 ...JPA & Spring Data JPA 配置Maven依赖 配置数据源和JPA 创建POJO实体 数据持久化 使用Spring Data JPA接口(方式一) CrudRepository PagingAndSortingRepository JpaRepository ...
  • SpringBoot整合SpringDataJPA

    万次阅读 多人点赞 2019-05-23 18:23:05
    一、SpringBootData JPA介绍   SpringData:其实SpringData就是Spring提供了一个操作数据的框架。而SpringData JPA只是SpringData框架下的一个基于JPA标准操作数据的模块。   SpringData JPA:基于JPA的标准数据...
  • springboot 整合 Mybatis、JPA、Redis

    万次阅读 多人点赞 2020-07-01 15:04:16
    下面我们分别整合mysql ,spring data jpa 以及redis 。让我们感受下快车道。 我们首先创建一个springboot 项目,创建好之后,我们来一步步的实践。 使用mybatis 引入依赖: <dependency> <groupId>org....
  • SpringBoot2.x【三】使用 JPA 快速开发

    万次阅读 2019-11-14 14:39:39
    SpringBoot2.x【三】使用 JPA 快速开发 什么是JPA? 一种规范,并非ORM框架,也就是ORM上统一的规范 用了之后可以做什么,为什么要用? 代码解释: 实体类 package com.example.springredis.entity; import ...
  • 目录 ...本文仅对如何在Springboot中使用Spring Data JPA和JdbcTemplate去操作多个HikariCP数据源进行简单示例和介绍,项目的完整目录层次如下图所示。 添加依赖与配置 为了使用Spring Data ...

空空如也

1 2 3 4 5 ... 20
收藏数 168,828
精华内容 67,531
关键字:

jpa