Spring data jpa的使用说明

本文介绍了Spring Data JPA的基本概念,详细讲解了如何配置数据源、实体管理工厂和事务,以及如何创建实体类和DAO接口。重点讨论了一对多和多对多关系的配置及操作,包括增删改查的方法,并提供了相关示例。
摘要由CSDN通过智能技术生成

1.什么是spring data jpa?

是一种基于jpa进行的再次封装的框架,其底层原理还是由其他框架实现的(这里用的是hibernate)

2.配置的过程

(1)创建一个maven工程,在pom文件中导入相应的坐标。

单元测试 junit 4.9
Aspectjweaver 支持切入点表达式和aop相关注解
Spring相关 版本都是4.2.4.RELEASE
Spring-aop aop切面编程的支持包
Spring-test 单元测试和集成测试的简单封装
Spring-context Spring提供在基础IoC功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等
Spring-context-support 拓展支持,用于MVC方面
Spring-beans spring ioc的基础实现
Spring-core spring核心组件
Spring-orm 整合第三方的orm框架
Hibernate相关 版本 5.0.7.Final
Hibernate-core hibernate核心包
Hibernate-entitymanager 实体管理包(和jpa整合)
Hibernate-validator 参数校验
C3p0 0.9.1.2 连接池
Log4j 1.2.12 日志
Slf4j-log4j12 1.6.6
Mysql-connector-java 5.1.6 数据库
Spring-data-jpa 1.9.0.RELEASE spring-data-jpa 核心包
Javax.el-api 2.2.4 必须导入的包
Javax.el 2.2.4

(2)在applicationContext中编写对应的配置文件。

1.配置数据源

 <context:property-placeholder location="classpath:jdbc.properties"/><!-- 定义引用的文件,这样写容易改动-->
    <context:component-scan base-package="com.cn"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><!-- c3p0数据源-->
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

2.配置实体管理工厂bean

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        //配置数据源
        <property name="dataSource" ref="dataSource"/>
        //指定扫描实体类的包
        <property name="packagesToScan" value="com.cn.entity"/>
        //配置持续化提供者
        <property name="persistenceProvider">
        //使用的是hibernate
            <bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
            //配置jpa适配器
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            //是否创建表
                <property name="generateDdl" value="false"/>
                //使用的数据库
                <property name="database" value="MYSQL"/>
                //使用的数据库方言
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                //是否显示sql语句
                <property name="showSql" value="true"/>
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
            //配置在更新时,是否创建表,创建表是否删除之前表的内容
                <prop 
                key="hibernate.hbm2dd1.auto">update</prop>
            </props>
        </property>
    </bean>

3.配置事务和jpa的相关配置。

 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    //jpa:repositories jpa仓库 需要指定dao放置的位置 base-package
    <jpa:repositories base-package="com.cn.dao" transaction-manager-ref="transactionManager"
                      entity-manager-factory-ref="entityManagerFactory"/>

(3)创建实体类

将注解映射到数据库表中,配置和jpa配置相同

(4)编写实体类的dao接口

需要继承两个接口JpaRepository<T,ID>和JpaSpecificationExecutor
T 代表实体类 ID代表 实体类的主键

public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>

1.JpaRepository<T,ID>提供了一些简单的数据库操作方法
FindOne 通过主键查询单个
Sava 保存,如果有主键就更新,没有就添加
Delete 通过主键删除
FindAll 查询所有
2.复杂的操作有多种方式进行查询

  1. JPQL查询(查询需要加上Query注解,修改还需要加上Modifying注解)
    //查询
    @Query(value = "from Customer  where custName= ? ")
    Customer findByName(String name);
    //更新,1代表第一个参数,2代表第二个参数,表示方法定义的时候两个参数的顺序
    @Query(value = "update Customer set custName=?1 where custId=?2")
    @Modifying
    void update(String custName,long custId);

调用更新方法的时候,因为需要对数据库内容进行修改,所以需要配置事务注解
@Transactional
@Rollback(value = false)

  1. 使用sql语句
   //查询
   @Query(value = "select * from cst_customer",nativeQuery = true)
    public List<Customer> findBySql();
   //更新    
   @Query(value = "update cst_customer set cust_name=? where cust_id=?",nativeQuery = true)
   @Modifying
   void updatesql(String custName,long custId);

使用sql语句,只需要在@Query注解上面加上nativeQuery = true就可以了,其余和jsql的方式一样

3.使用方法查询,由jpa内部自动生成sql语句进行创建

jpa方法查询
方法查询的规范
find+全局修饰+By+实体属性名称+限定词+连接词+(其他实体属性)+OrderBy+排序属性+排序方向
如:findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(String firstName,String lastName)
方法查询规范
4.使用Spring data jpa 中JpaSpecificationExecutor接口
我们要使用其中的方法就必须了解Specification接口 它定义了一个方法toPredicate 其中 有三个参数Root (代表想要查询表的实体类) CriteriaQuery 顶层查询 CriteriaBuilder 具体查询标准
①相关查询
精确查询: cb.equla(root.get(“custName”),”哈哈”);
并列查询:
cb.equla(root.get(“custName”),”哈哈”);
cb.equla(root.get(“custId”),”1”);
cb.and(p1,p2);
模糊查询:
cb.like(root.get(“custName”).as(String.class),”哈%”);
排序查询:
排序查询只需要创建一个排序对象
Sort sort=new Sort(Sort.Direction.DESC,”custName”);第一个参数代表排序方式,第二个表示通过哪个属性排序
分页查询:
分页查询需要一个Pageable对象这个 声明该对象 Pageable pageable=new PageRequest(0,3) 第一个参数从哪开始 第二个参数 一页有几个数据
然后通过customerDao接口调用方法 返回一个分页对象 这个对象是spring data jpa 所提供的 里面包含分页需要的所有属性
totalElements获总数据数量 totalPages 获得一页有几个数据
content 表示 返回的内容

//一般查询
Specification<Customer> spec=new Specification<Customer>(){

            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //root就是 相当于实体类对象 query 自定义查询 cb:构建查询
                return cb.like(root.get("custName").as(String.class),"7%");
            }
        };
        List<Customer> all = customerDao.findAll(spec);
//排序查询
customerDao.findAll(new Sort(Sort.Direction.DESC,"custName")
//分页查询
        Pageable pageable=new PageRequest(0,3);
        Page<Customer> customers = customerDao.findAll(pageable);
        System.out.println(customers.getTotalElements());
        System.out.println(customers.getTotalPages());
        System.out.println(customers.getContent());        

3.关于一对多和多对多的操作

(1)一对多

一的一方:

/* @OneToMany(targetEntity = LinkMan.class)
    @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")*/
   @OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
    private Set<LinkMan> linkmans=new HashSet<LinkMan>();

多的一方:

@ManyToOne(targetEntity = Customer.class,fetch =FetchType.LAZY )
    @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
   private Customer customer;

① 主要区别在于 在实体类中 要和 其他类有关系

操作在于
1的一方需要有一个存储多的一方的集合,并且需要加上注释@OneToMany(mappedBy=”customer”,cascade=Cascade.Type.ALL)
其中mappedBy 表示放弃维护权,第二个代表级联操作:操作一个对象同时操作它的关联对象
为何要放弃维护权?
因为多对一方再保存的时候已经保存了外键信息,所以不需要再进行更新了
多的一方需要添加一个一的一方的对象同时需要加上注释
@ManyToOne(targetEntity=Customer.class,fetch=FetchType.LAZY)
@JoinColumn(name=”lkm_cust_id”,referencedColumnName=”cust_id”)
第一个代表多对一,属性为 目标实体类 需要一方面的字节码文件,还可以配置加载方式 LAZY为懒加载,EAGER为直接加载
第二个注释中 名字为 外键名,第二个为该外键在主表的名字

② 多表操作(1对多)增删改查

Add:需要加上@Transaction和@Rollback(注释)
添加的时候 因为使用级联操作,所以只需要在主方进行保存(一方)
Delete:删除的时候,一方删除就可以了
Update:无特殊
Search:查询的时候通过对象导航进行查询,但是再toString方法中一定要删除其中一个的输出另一个类的方法,不然会无限循环,出错 同时查询要加上@Transactional注释

(2)多对多

双方:

//role方
 @ManyToMany(targetEntity = User.class,cascade = CascadeType.ALL)
    @JoinTable(name = "role_user",joinColumns = {
            @JoinColumn(name = "ru_role_id",referencedColumnName = "role_id")
    },inverseJoinColumns = {
            @JoinColumn(name = "ru_user_id",referencedColumnName = "user_id")
    })
    private Set<User> users=new HashSet<User>();
    ---------------------------------------------
   //user方
     @ManyToMany(mappedBy = "users")
    private Set<Role> roles=new HashSet<Role>();

①配置相关说明

建议多对多的时候也是 一个负责 维护 一个放弃
需要在两个类中各加入一个对方的集合
在集合上面进行配置

主 类 @ManyToMany(targetEntity=User.class,cascade=CascadeType.ALL)
@JoinTable(name=”role_user”,joinColumns={
@JoinColumn(name=”ru_role_id,referencedColumnName=”role_id”)
},inverseJoinColumns={@JoinColumn(name=”ru_user_id”,referencedColumnName=”user_id”)}
)
其中JoinTable为中间表
joinColumns 中 name为中间表中的主外键名 referencedColumnName为 主表中名
inverseJoinColumns中第一个为中间表中另一个表的外键名 referencedColumnName为 另一个表中的主表外键名

第二个类只需要在集合方法上加上@ManyToMany(mappedBy=”users”)

② 多表操作增删改查

增加:主类操作
删除:主类进行删除(会删除所有相关)
修改:各改各的
查:互相的都可以查,但是toString中 要删除一个 否则会报错
一方查多方:默认延迟加载,因为多方数据多
多方查一方:默认即时加载,因为一方数据只有一条

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值