JPA基础知识

JAP的由来

ORM框架能够将Java对象映射到关系型数据库中,能够直接持久化复杂的Java对象。ORM的出现让开发者从数据库编程中解脱出来,把更多的精力放在业务模型与业务逻辑,目前流行的ORM框架有MyBatis,Hibernate,JDO等。

JPA是什么?

JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据,它的出现简化现有的持久化开发工作和整合ORM技术,结束了MyBatis,Hibernate,JDO各自经营的局面。

JPA充分吸收了现有的MyBatis,Hibernate,JDO等ORM框架的基础上发展而来的,易于使用,伸缩性强等优点。

注意:
JPA是一套规范,不是一套产品,MyBatis,Hibernate,JDO框架是一套产品,如果这些产品实现了JPA规范,那么我们称它们为JPA的实现产品

JPA=Java Persistence APIJava持久化API
MyBatis,Hibernate,JDO 框架都是一种实现。

Spring Data JPA

Spring Data是Spring的一个子项目,用于简化数据库访问,NoSQL非关系型数据库,还包括对关系型数据库的访问之处,所有数据库访问都要通过Spring Data,Spring Data让数据库访问变的更加方便

Spring Data JPA让我们解脱了DAO层的操作,基本上所有CRUD(增删改查)都可以依赖于它的实现。

配置数据源-配置JPA相关信息
#配置数据源相关信息
#MYSQL5.x版本的驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/crm?useUnicode=true&amp&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root

#配置JPA(Hibernate)相关信息
#spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

hibernate.hbm2ddl.auto参数的作用主要用于:创建、更新、验证数据库表结构

create:
如果设置为该值,则每次加载hibernate时(准确说应是创建SessionFactory时)都会删除以前创建的表而根据model重新生成表,即使前后的表没有任何变化,通常会造成数据库数据丢失,需谨慎使用这个取值

create-drop:
与create差不多,所不同的是每次sessionFactory关闭时,就会删除所有表

update:
这个取值比较常用,需要先建立数据库,在第一次加载hibernate时会自动创建表,以后创建hibernate会自动根据model更新表结构,即使表结构改变了,以前的行不会被删除

validate:
每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值

hibernate.dialect:
主要是指定数据库方言(数据库类型)

show-sql:
是否在日志中打印出自动生成的SQL,方便调试的时候查看

format_sql:
是否格式化SQL

IDEA连接Mysql数据库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第一步创建实体类

创建User.java实体类
package com.li.jap.model;

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

@Entity
@Table(name = "sys_user")
@NamedQueries(@NamedQuery(name = "User.findUsersByName",query = "select u from User u where u.usrName=:usrname"))
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "usr_id")
    private  Long usrId;
    @Column(name = "usr_name")
    private  String usrName;
    @Column(name = "usr_password")
    private  String usrPassword;
    @Column(name = "usr_role_id")
    private  Long usrRoleId;
    @Column(name = "usr_flag")
    private  Integer usrFlag;

@Entity 表明该类 (UserEntity) 为一个被JPA管理的实体类,它默认对应数据库中的表名是sys_user。

@Table: 当实体类与其映射的数据库表名不同名时需要使用 @Table注解说明,该标注与 @Entity 注解并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。

@Column:当实体的属性与其映射的数据库表的列不同名时需要使用@Column 标注说明,该属性通常置于实体的属性声明语句之前(置于属性的getter方法之前),还可与 @Id 标注一起使用。

@Id: 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上,但一个实体类里面必须有一个。 @Id标注也可置于属性的getter方法之前。

@GeneratedValue:主要就是为一个实体生成一个唯一标识的主键、@GeneratedValue提供了主键的生成策略。

@Transient并非一个到数据库表的字段的映射,表示非持久化属性

@Enumerated直接映射enum 枚举类型的字段点击查看详情

第二步编写Repository

public interface UserRepository extends JpaRepository<User,Long> , JpaSpecificationExecutor<User> {
}

JpaRepository继承PagingAndSortingRepository和QueryByExampleExecutor。
PagingAndSortingRepository类主要负责排序和分页内容。
QueryByExampleExecutor类提供了很多示例的查询方法。

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
}

继承JpaRepository的Repository会自动用于示例的查询方法和排序、分页功能。

PagingAndSortingRepository又继承了CrudRepository

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
}

CrudRepository内置了增、删、改、查的方法。

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {

	/**
	 * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
	 * entity instance completely.
	 *
	 * @param entity must not be {@literal null}.
	 * @return the saved entity; will never be {@literal null}.
	 * @throws IllegalArgumentException in case the given {@literal entity} is {@literal null}.
	 */
	<S extends T> S save(S entity);

	/**
	 * Saves all given entities.
	 *
	 * @param entities must not be {@literal null} nor must it contain {@literal null}.
	 * @return the saved entities; will never be {@literal null}. The returned {@literal Iterable} will have the same size
	 *         as the {@literal Iterable} passed as an argument.
	 * @throws IllegalArgumentException in case the given {@link Iterable entities} or one of its entities is
	 *           {@literal null}.
	 */
	<S extends T> Iterable<S> saveAll(Iterable<S> entities);

	/**
	 * Retrieves an entity by its id.
	 *
	 * @param id must not be {@literal null}.
	 * @return the entity with the given id or {@literal Optional#empty()} if none found.
	 * @throws IllegalArgumentException if {@literal id} is {@literal null}.
	 */
	Optional<T> findById(ID id);

	/**
	 * Returns whether an entity with the given id exists.
	 *
	 * @param id must not be {@literal null}.
	 * @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
	 * @throws IllegalArgumentException if {@literal id} is {@literal null}.
	 */
	boolean existsById(ID id);

	/**
	 * Returns all instances of the type.
	 *
	 * @return all entities
	 */
	Iterable<T> findAll();

	/**
	 * Returns all instances of the type {@code T} with the given IDs.
	 * <p>
	 * If some or all ids are not found, no entities are returned for these IDs.
	 * <p>
	 * Note that the order of elements in the result is not guaranteed.
	 *
	 * @param ids must not be {@literal null} nor contain any {@literal null} values.
	 * @return guaranteed to be not {@literal null}. The size can be equal or less than the number of given
	 *         {@literal ids}.
	 * @throws IllegalArgumentException in case the given {@link Iterable ids} or one of its items is {@literal null}.
	 */
	Iterable<T> findAllById(Iterable<ID> ids);

	/**
	 * Returns the number of entities available.
	 *
	 * @return the number of entities.
	 */
	long count();

	/**
	 * Deletes the entity with the given id.
	 *
	 * @param id must not be {@literal null}.
	 * @throws IllegalArgumentException in case the given {@literal id} is {@literal null}
	 */
	void deleteById(ID id);

	/**
	 * Deletes a given entity.
	 *
	 * @param entity must not be {@literal null}.
	 * @throws IllegalArgumentException in case the given entity is {@literal null}.
	 */
	void delete(T entity);

	/**
	 * Deletes the given entities.
	 *
	 * @param entities must not be {@literal null}. Must not contain {@literal null} elements.
	 * @throws IllegalArgumentException in case the given {@literal entities} or one of its entities is {@literal null}.
	 */
	void deleteAll(Iterable<? extends T> entities);

	/**
	 * Deletes all entities managed by the repository.
	 */
	void deleteAll();
}

JpaRepository继承了PagingAndSortingRepository,PagingAndSortingRepository又继承了CrudRepository,所以JpaRepository默认拥有上述方法。
在这里插入图片描述
第三步测试用例

@RunWith(SpringRunner.class)
@SpringBootTest
class JapApplicationTests {
    @Resource
    private UserRepository userRepository;

    @Test
    void contextLoads() {
        User user = new User("JPA","123456",8L,1);
        userRepository.save(user);
    }
    @Test
    public void testGet(){
        User user = userRepository.findById(1L).get();
        System.out.printf("usrName"+user.getUsrName());
    }
 }
复杂操作
自定义QL查询

模糊查询

 //模糊查询
    public List<User> findByUsrNameLike(String usrName);

使用自定义QL查询 维护可读性。

//使用自定义QL查询   维护可读性。
@Query("select u from  User u where u.usrRoleId=:roleId")
public User findByRoleId(@Param("roleId") Long roleId);

修改删除操作

//修改删除操作
@Transactional(timeout = 10)   //对事务的支持,操作超时设置
@Modifying
@Query("update User u set u.usrName=:usrname where u.usrId=:usrid")
public int modifyNameById(@Param("usrname")String usrname,
                          @Param("usrid") Long usrid);
命名QL查询

在实体类上添加@NamedQueries注解

@NamedQueries(@NamedQuery(name = "User.findUsersByName",query = "select u from User u where u.usrName=:usrname"))
分页查询

Pageable 是Spring封装的分页实现类,使用的时候需要传入页数,每页条数和排序规则。
Page是Spring封装的分页对象,封装了总页数,分页数据等,返回对象除了使用Page外,还可以使用Slice作为返回值。

   @Query("select  u from User u where u.usrRoleId=:roleId")
    public Page<User> findPageByUsrRoleId(@Param("roleId") Long roleId, Pageable pageable);

Page和Slice的区别如下:

  1. Page接口继承自Slice接口,而Slice继承自Iterable接口。
  2. Page接口扩展了Slice接口,添加了获取总页数和元素总数量的方法,因此返回Page接口时,必须执行两条SQL,一条查询分页数据,一条负责查询总数量
  3. 返回Slice结果时,查询的SQL只会有查询分页数据这一条,不统计数据数量。
  4. 值得注意的是,Page实现了获取所有记录的数量和页面的总数,但是它是通过count query来计算的,所以当数据源大的时候,就会显示出劣势;但是Slice在做某些操作的时候并不需要把所有的记录数都计算一次!
 @Test
    public void testFindPageByUsrRoleId(){
        int page = 0,size=2; //分页要素,页数从0开始
        //控制分页数据的排序,可以选择升序和降序
        Sort sort= Sort.by(Sort.Direction.DESC,"usrId");
        //控制分页的辅助类,可以设置页码,每页的数据条数,排序等
        Pageable pageable = PageRequest.of(page,size,sort);
        Page<User> userPage = userRepository.findPageByUsrRoleId(8L,pageable);
        System.out.println("总记录数:"+userPage.getTotalElements());
        System.out.println("总页数:"+userPage.getTotalPages());
        System.out.println("当前页数:"+(userPage.getNumber()+1));
        System.out.println("每页记录数:"+userPage.getSize());
        System.out.println("当前页记录数:"+userPage.getNumberOfElements());
        for (User user : userPage.getContent()){//获得查询的数据
            System.out.println("usrId:"+user.getUsrName());
        }
    }

点击查看========Java语言基础知识

点击查看========Spring Boot入门知识

点击查看========Java虚拟机

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值