Spring boot JPA

一、定义

  JPA(Java Persistence API),Java持久化API,是定义对象关系映射(ORM)以及实体对象持久化的标准接口。JPA是JSR-220(EJB3.0)规范中的一部分,但是在JSR-220中规定实体对象(Entity Bean)由JPA进行支持,所以JPA不局限于EJB3.0,而是作为POJO持久化的标准规范,可以脱离容器独立运行、开发和测试。然和这套方案并未被企业广泛使用,相对地JPA更多的是依靠Hibernate的支持才的事使用。

  在SpringBoot中JPA是一开Hibernate猜的是实现,Hibernate在3.2版本中已经对JPA实现了完全的支持。

  JPA所维护的核心是实体(Entity Bean),而它是通过一个持久化上下文(Persistence Context)来使用的。持久化上下文包含以下3个部分

    对象关系映射(Object Relational Mapping,简称ORM)描述,JPA支持注解和XML两种方式的描述,在Spring Boot中主要通过注解实现;

    实体操作API,实现岁实体对象的CRUD操作,完成对象的查询和持久化;

    查询语言,约定了面向对象的查询语言JPQL(Java Persistence Query Language),实现灵活的查询

 

二、JPA注解

  @Entity :表明是一个实体类、

  @Table :属性name指出映射数据库的表,这样实体就映射到对应的表上

  @Id :标注属性为表的主键

  @GeneratedValue :和@Id组合使用,致命主键采用何种侧路由说呢过成主键

    GenerationType.IDENTITY,是要数据库递增策略

    GenerationType.AUTO,主键由程序控制

    GenerationType.ENERATOR,指定生成主键使用的生成器

    GenerationType.TABLE,使用一个特定的数据库来保存主键

    GenerationType.SYSTEM-UUID,使用系统生成的UUID进行配

  @Column :通过指定name属性的值,关联数据库表的列

    name字段用于指定映射到表结构的映射字段。

    length代表此字段的长度约束,可以省略。

    unique属性代表此字段是否开启唯一性约束,默认为false,唯一则为true 。

    nullable代表此字段是否可以为空,默认为true 。 false代表不能为空 。

    @DateTimeFormat用于映射数据库表时间的格式。

  @Temporal :如果某个实体类的字段包含 Date类型,那么数据库中应该存储的是 “yyyy-MM-dd hh:MM:ss”的形式,针对这种形式的存储,@Temporal 有三种注解值对应

    第一种:@Temporal(TemporalType.DATE)——》实体类会封装成日期“yyyy-MM-dd”的 Date类型。

    第二种:@Temporal(TemporalType.TIME)——》实体类会封装成时间“hh-MM-ss”的 Date类型。

    第三种:@Temporal(TemporalType.TIMESTAMP)——》实体类会封装成完整的时间“yyyy-MM-dd hh:MM:ss”的 Date类型。

  @Query:定义SQL查询

    nativeQuery = true ,说明定义的SQL是原生sql语句(所谓原生sql,也就是说这段sql拷贝到数据库中,然后把参数值给一下就能运行了),分页必须设为true

  @Modifying : 在@Query注解中编写JPQL实现DELETE和UPDATE操作的时候必须加上@modifying注解,以通知Spring Data 这是一个DELETE或UPDATE操作

      一版要结合@Transactional注解一起使用

  @NamedQueries :属性name指定命名查询的名称,query属性指定命名查询的语句,在Entity上注释,不推荐使用

@Entity
@Table(name="t_user")
@NamedQueries({
        @NamedQuery(name="findAllUser",query="SELECT u FROM User u"),
        @NamedQuery(name="findUserWithId",query="SELECT u FROM User u WHERE u.id = ?1"),
        @NamedQuery(name="findUserWithName",query="SELECT u FROM User u WHERE u.name = :name")
})
public class User {
     
    /**
     * 主键
     */
    @Id
    @GeneratedValue
    private Long id;

    /**
     * 名字
     */
    @Column(name="name")
    private String name;
}
public class TestNamedQuery {
     
    EntityManagerFactory emf = null;
     
    @Before
    public void before() {
        //根据在persistence.xml中配置的persistence-unit name 创建EntityManagerFactory
        emf = Persistence.createEntityManagerFactory("myJPA");
    }
     
    @After
    public void after() {
        //关闭EntityManagerFactory
        if(null != emf) {
            emf.close();
        }
    }
     
    @Test
    public void testNamedQuery1() {
        EntityManager em = emf.createEntityManager();
        List<User> users = em.createNamedQuery("findAllUser").getResultList();//根据User实体中定义的命名查询
    }
     
    @Test
    public void testNamedQuery2() {
        EntityManager em = emf.createEntityManager();
        Query query =  em.createNamedQuery("findUserWithId");//根据User实体中定义的命名查询
        query.setParameter(1, 2L);
        List<User> users = query.getResultList();
    }
     
    @Test
    public void testNamedQuery3() {
        EntityManager em = emf.createEntityManager();
        Query query =  em.createNamedQuery("findUserWithName");//根据User实体中定义的命名查询
        query.setParameter("name", "李坏");
        List<User> users = query.getResultList();
    }
}

 

三、SpringBoot使用JPA

  1、pom.xml依赖

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <!-- 排除默认的连接池 -->
            <!-- <exclusions>
                <exclusion>
                     <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions> -->
        </dependency>
        <!-- 连接池:HikariCP性能最好 -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>    

 

  2、application.yml配置,数据库、连接池配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/dl?useUnicode=true&serverTimezone=UTC&characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 10
      maximum-pool-size: 25
      auto-commit: true
      idle-timeout: 30000
      pool-name: ExpendHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1
  jpa:
    database-platform : org.hibernate.dialect.MySQLDialect

 

  3、定义查询方式,目前有三种查询方式

    a、方法命名查询 :方法名称组合

    //根据id查找
    public Order findById(@Param("id")String id);
    
    //查找全部的记录
    public List<Order> findAll();
    
    //根据订单号和id查找
    public Order findByOrderNoAndStatus(@Param("orderNo")String orderNo,@Param("status")int status);
    
    //通过订单状态查找前10条记录
    public List<Order> findFirst10ByStatus(@Param("status")int status);
    
    //通过订单状态查找前30条记录
    public List<Order> findTop30ByStatus(@Param("status")int status);
    
    //根据订单号删除记录
    public void deleteByOrderNo(@Param("orderNo")String orderNo);

 

 

    b、@NamedQuery查询   : 即一个名称映射一个查询语句(要在实体类上写,不是接口里写)

@Entity
@NamedQuery(name="Person.findByName",query="select p from Person p where p.name=?1")
public class Person{

}

 

    c、@Query查询

    //普通多条件查询
    @Query("select p from Order where p.payMethod = :payMethod and p.status = :status")
    public List<Order> findByPayMethodAndStatus(@Param("payMethod")String payMethod,@Param("status")int status);
    
    //分页查询 ,nativeQuery
    @Query(value="select * from tbl_order o where o.payMethod= :payMethod order by o.createTime desc LIMIT :start,:end",nativeQuery=true)
    Integer findRechargeRecord(@Param("payMethod") int payMethod,@Param("start") int start,@Param("end") int end);
    
    //修改订单状态,返回更新语句所影响的条数
    @Modifying
    @Query("update Order o set o.status = :status where o.ordrerNo = :orderNo")
    int updateByOrderNo(@Param("orderNo")String orderNo,@Param("status")int status);

 

 

四、使用JPA Tools自动生成Entity对象

  参考链接:https://www.cnblogs.com/zzllx/p/6481173.html

  MYSQL jar包下载地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.41

  1、注意表名的转换:例如表名前缀是tbl_user,生成的Entity就是 TblUser,如果不需要前缀,可以自行修改为User;

  2、自动生成的Entity,没有添加主键策略,例如自增长,可以自行添加 @GeneratedValue(strategy=GenerationType.IDENTITY);

  3、如果使用lombok,可以自行替换

  4、JPA映射text类型,@Lob代表是长字段类型,默认的话,是longtext类型,所以需要下面这个属性来指定对应的类型。

    columnDefinition="text"里面的类型可以随意改,后面mysql可能会有新的类型,只要是对应java的String类型,就可以在这里动态配置。

    @Lob
    @Column(columnDefinition="text")
    public String explainStr;

 

常见问题解答

  一、The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration.....

    链接地址 : https://blog.csdn.net/aayygg1234/article/details/78205240

  二、unknown column"***_***" in where clause  (驼峰自动转换成下划线,导致找不到)

    链接地址:https://blog.csdn.net/u013030980/article/details/78135335

posted on 2019-04-09 20:15  levi~liu  阅读(267)  评论(0)    收藏  举报

导航