SpringDataJpa

JPA案例

搭建环境

创建maven工程,导入坐标
<dependencies>
    <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>5.0.7.Final</version>
    </dependency>

    <!--c3p0-->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>5.0.7.Final</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.19</version>
    </dependency>
</dependencies>
配置jpa的配置文件
  • 位置:配置到类路径下META-INF的文件夹下
  • 命名:persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <!--
        需要配置persistence-unit节点
        持久化单元:
            name:持久化单元名称
            transaction-type:事务管理的方式
                JTA:分布式事务管理
                RESOURCE_LOCAL:本地事务管理
    -->
    <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
        <!--jpa的实现方式-->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <!--
            数据库信息
                用户名:javax.persistence.jdbc.user
                密码: javax.persistence.jdbc.password
                驱动: javax.persistence.jdbc.driver
                url: javax.persistence.jdbc.url
        -->
        <properties>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="1234"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///dev?serverTimezone=UTC"/>
            <!--
                可选配置:配置实现jpa实现方(hibernate)的配置信息
                    显示sql           :true|false
                    自动创建数据库表    :hibernate.hbm2ddl.auto
                            create   :程序运行时创建数据库表(如果有表,先创建表再创建)
                            update   :程序运行时创建表(如果有表不会创建表)
                            none     :不会创建表
            -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>
    </persistence-unit>
    
</persistence>
编写客户的实体类 配置实体类和表,类中属性和表中字段的映射关系
/**
 * 客户的实体类
 * @Entity 声明实体类
 * @Table 配置实体类和表的映射关系
 *      name:配置数据库表的名称
 */
@Entity
@Table(name = "cst_customer")
public class Customer {

    /**
     * @Id 声明主键的配置
     * @GeneratedValue 配置主键的生成策略
     *      GenerationType.IDENTITY :自增(mysql)
     *          底层数据库必须支持自动增长
     *      GenerationType.SEQUENCE :序列(oracle)
     *          底层数据库必须支持序列
     *      GenerationType.TABLE :jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
     *      GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
     * @Column 配置属性和字段的映射关系
     *      name:数据库表中字段的名称
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Long custId;//客户主键

    @Column(name = "cust_name")
    private String custName;//客户名称

    @Column(name = "cust_source")
    private String custSource;//客户来源

    @Column(name = "cust_lever")
    private String custLever;//客户级别

    @Column(name = "cust_industry")
    private String custIndustry;//客户所属行业

    @Column(name = "cust_phone")
    private String custPhone;//客户联系方式

    @Column(name = "cust_address")
    private String custAddress;//客户地址

    @Override
    public String toString() {
        return "Customer{" +
                "custId=" + custId +
                ", custName='" + custName + '\'' +
                ", custSource='" + custSource + '\'' +
                ", custLever='" + custLever + '\'' +
                ", custIndustry='" + custIndustry + '\'' +
                ", custPhone='" + custPhone + '\'' +
                ", custAddress='" + custAddress + '\'' +
                '}';
    }

    public Long getCustId() {
        return custId;
    }

    public void setCustId(Long custId) {
        this.custId = custId;
    }

    public String getCustName() {
        return custName;
    }

    public void setCustName(String custName) {
        this.custName = custName;
    }

    public String getCustSource() {
        return custSource;
    }

    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }

    public String getCustLever() {
        return custLever;
    }

    public void setCustLever(String custLever) {
        this.custLever = custLever;
    }

    public String getCustIndustry() {
        return custIndustry;
    }

    public void setCustIndustry(String custIndustry) {
        this.custIndustry = custIndustry;
    }

    public String getCustPhone() {
        return custPhone;
    }

    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }

    public String getCustAddress() {
        return custAddress;
    }

    public void setCustAddress(String custAddress) {
        this.custAddress = custAddress;
    }
}
测试保存客户到数据库中
@Test
    public void testInsert(){

        //1.加载配置文件,创建实体类管理器工厂
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
        //2.通过实体管理器工厂获取实体管理器
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        //3.获取事务管理器
        EntityTransaction transaction = entityManager.getTransaction();
        //4.开启事务
        transaction.begin();
        Customer customer = new Customer();
        customer.setCustName("xiaojiang");
        customer.setCustAddress("luoyangshi");
        //5.保存
        entityManager.persist(customer);
        //6.提交事务
        transaction.commit();
        //7.释放资源
        entityManager.close();
        entityManagerFactory.close();

    }
解决 java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException**

原因:jdk版本过高,9以上就会报错
解决方法:maven中加入依赖

<dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

jpa操作步骤

  • 1)、加载配置文件创建实体类管理工厂
    Persistence:静态方法createEntityManagerFactory(“myJpa”)(根据持久化单元名称创建实体类管理工厂)
    作用:创建实体类管理工厂

  • 2)、根据实体类管理工厂创建实体类管理器
    EntityManagerFactory:获取EntityManager对象
    方法createEntityManager()

    • 内部维护了很多的内容
      数据库信息
      缓存信息
      所有的实体管理器对象
      在创建EntityManagerFactory的过程中会根据配置创建数据库表
  • EntityManagerFactory创建过程比较浪费资源
    特点:线程安全的对象
    如何解决EntityManagerFactory的创建过程浪费资源的问题

    • 静态代码块形式创建一个公共的EntityManagerFactory对象
    public class JpaUtil {
    
        private static EntityManagerFactory entityManagerFactory;
    
        static {
            entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
        }
    
        public static EntityManager getEntityManager(){
            return entityManagerFactory.createEntityManager();
        }
    
    }
    
  • 3)、创建事务对象
    EntityManager对象:实体类管理器

    • getTransaction():创建事务对象
    • persist():保存
    • merge():更新
    • remove():删除
    • find/getRefrence() :根据id查询

    Transaction对象:事务

    • begin(): 开启事务
    • conmmit():提交事务
    • rollback():回滚事务
  • 4)、增删改查操作

  • 5)、提交事务/回滚事务

  • 6)、释放资源

/**
     * 查询的对象就是当前实体类对象
     * 在调用方法的时候就发送sql语句查询数据库
     */
    @Test
    public void testFind(){
        EntityManager entityManager = JpaUtil.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        Customer customer = entityManager.find(Customer.class, 1l);
        transaction.commit();
        System.out.println(customer);
        entityManager.close();
    }

    /**
     * 获取的对象是个动态代理对象
     * 调用getReference方法不会立即发送sql语句查询数据库,当调用查询结果对象的时候才会发送查询的sql语句
     * 延迟加载(懒加载)
     */
    @Test
    public void testReference(){
        EntityManager entityManager = JpaUtil.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        Customer customer = entityManager.getReference(Customer.class, 1l);
        transaction.commit();
        System.out.println(customer);
        entityManager.close();
    }

    @Test
    public void testMerge(){
        EntityManager entityManager = JpaUtil.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        Customer customer = entityManager.getReference(Customer.class, 1l);
        customer.setCustAddress("jianxiqu");
        entityManager.merge(customer);
        transaction.commit();
        entityManager.close();
    }

    @Test
    public void testRemove(){
        EntityManager entityManager = JpaUtil.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        Customer customer = entityManager.getReference(Customer.class, 1l);
        entityManager.remove(customer);
        transaction.commit();
        entityManager.close();
    }

SpringDataJpa案例

搭建环境

导入依赖
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.10.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>2.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>

编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jdbc
        https://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/data/jpa
        https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <!--创建entityManagerFactory对象-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--实体类所在包-->
        <property name="packagesToScan" value="ganxie.xiaowen.jpa.bean"/>
        <!--jpa的实现厂家-->
        <property name="persistenceProvider">
            <bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
        </property>
        <!--jpa的供应商适配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--指定数据库类型-->
                <property name="database" value="MYSQL"/>
                <!--数据库支持的特有语法-->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                <!--是否自动创建数据库表 -->
                <property name="generateDdl" value="false"/>
                <!--是否显示sql语句-->
                <property name="showSql" value="true"/>
            </bean>
        </property>
        <!--jpa的高级特性-->
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
        </property>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="root"/>
        <property name="password" value="1234"/>
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql:///dev?serverTimezone=UTC"/>
    </bean>

    <!--整合spring data Jpa-->
    <jpa:repositories base-package="ganxie.xiaowen.jpa.dao" entity-manager-factory-ref="entityManagerFactory"
                      transaction-manager-ref="transactionManager"/>

    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <!--包扫描-->
    <context:component-scan base-package="ganxie.xiaowen.jpa"/>
    <!--声明式事务-->
</beans>
编写实体类并将实体类和表,属性和字段一一对应
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "name")
    private String name;

    @Column(name = "address")
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
编写dao接口
/**
 * 符合springDataJpa的dao层接口,
 * 只需要继承两个接口JpaRepository,JpaSpecificationExecutor并提供相应的泛型
 * JpaRepository<封装的实体类,主键数据类型> 封装了基本CRUD操作
 * JpaSpecificationExecutor<封装的实体类> 封装了复杂查询
 */
public interface UserDao extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {
}

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestUserDao {

    @Autowired
    private UserDao userDao;

    @Test
    public void testFindAll() {
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }

    @Test
    public void testFindOne() {
        User user = userDao.findOne(1);
        System.out.println(user);
    }

    /**
     * 更新保存都是save()方法,如果传入的主键存在,就根据主键查找并修改
     * 如果传入的主键不存在,就执行保存操作。
     */
    @Test
    public void testInsert() {
        User user = new User();
        user.setName("test");
        user.setAddress("alibaba");
        userDao.save(user);
    }

    @Test
    public void testUpdate() {
        User user = new User();
        user.setId(4);
        user.setName("test");
        user.setAddress("fushan");
        userDao.save(user);
    }

    @Test
    public void testDelete() {
        userDao.delete(4);
    }
}

原理

  • 通过JdkDynamicAopProxy的invoke方法创建一个动态代理对象
  • SimpleJpaRepository当中封装了JPA的操作(借助JPA的api完成数据库的CRUD)
  • 通过hibernate完成数据库操作(封装了jdbc)

Specification

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestSpecification {

    @Autowired
    private UserDao userDao;

    /**
     * 测试查询
     */
    @Test
    public void testFind() {
        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<Object> id = root.get("id");
                Predicate equal = cb.equal(id, 1);
                return equal;
            }
        };
        User user = userDao.findOne(specification);
        System.out.println(user);
    }

    /**
     * 测试多条件查询
     */
    @Test
    public void testComplex() {
        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<Object> name = root.get("name");
                Path<Object> address = root.get("address");
                Predicate equal = cb.equal(name, "小兰");
                Predicate equal1 = cb.equal(address, "洛阳市");
                Predicate predicate = cb.and(equal, equal1);
                return predicate;
            }
        };
        User user = userDao.findOne(specification);
        System.out.println(user);
    }

    /**
     * 测试模糊查询并排序
     */
    @Test
    public void testLikeAndSort() {
        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<Object> name = root.get("name");
                Predicate predicate = cb.like(name.as(String.class), "小%");
                return predicate;
            }
        };
        Sort sort = new Sort(Sort.Direction.DESC,"id");
        List<User> users = userDao.findAll(specification,sort);
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * 测试分页查询
     */
    @Test
    public void testPage() {
        /**
         * PageRequest 是Pageable接口的实现类
         *      第一个参数:当前查询的页数(从0开始)
         *      第二个参数:每页查询的数量
         */
        PageRequest pageRequest = new PageRequest(0,2);
        Page<User> users = userDao.findAll(pageRequest);
        for (User user : users) {
            System.out.println(user);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值