Async

Async 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

80's|Coder|Rock|ACG|Si-Fi|ModelMaker|Geek|God is in his heaven,all's right with the world

个人动态

Async 回答了问题 · 2018-03-09

如何快速比较两个数值列表是否相等?

先判断个数是否相同;
建个set,遍历a,全丢进set,遍历b,挨个判断b元素是否在set中存在,如果有不存在的则说明不相同,整体时间复杂度O(1);
如果有重复元素,set里的对象加counta和countb记录a和b个元素数,最后再遍历一遍set对比counta,countb是否相同,整体时间复杂度也为O(1);

关注 3 回答 2

Async 回答了问题 · 2018-03-09

Java: 如果一个对象gc root不可达,但是对象内部某个变量gc root可达,这个对象会被回收吗?

如果外部的对象没有可达的root引用的话,会

关注 2 回答 1

Async 回答了问题 · 2018-03-08

解决前端怎样实现下载文件,而不暴露文件路径(不被抓包工具抓到)或者即使被抓到再次通过路径直接访问也拿不到文件

每次下载请求前先获取一个后台随机生成的一次性加密值,下载请求带上加密值,验证成功才能下载

关注 9 回答 9

Async 回答了问题 · 2018-03-08

解决mybatis 传入参数为2个对象的时候该怎么设置

用 @Param 注解,具体用法自己google吧

关注 3 回答 2

Async 收藏了文章 · 2018-03-08

慕课网_《轻松愉快之玩转SpringData》学习总结

时间:2017年04月24日星期一
说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com
教学示例源码:https://github.com/zccodere/s...
个人学习源码:https://github.com/zccodere/s...

第一章:课程介绍

1-1 课程介绍

什么是Spring Data

主旨:提供一个熟悉的、一致的,基于Spring框架的数据访问框架。
简化数据库的访问。
历史:2010年提出,作者Rod Johnso,Spring Source项目
网址:http://projects.spring.io/spring-data/#quick-start

Spring Data概览

clipboard.png

Spring Data包含多个子项目

Spring Data JPA
Spring Data Mongo DB
Spring Data Redis
Spring Data Solr

课程安排

传统方式访问数据库
Spring Data快速起步
Spring Data JPA进阶
Spring Data JPA高级

第二章:使用传统方式访问数据库

2-1 使用传统方式访问数据库

传统方式访问数据库

JDBC
Spring JdbcTemplate
弊端分析

2-2 准备工作

JDBC

Connection
Statement
ResultSet
Test Case

搭建开发环境

创建maven项目
添加数据库驱动和单元测试依赖
数据库表的准备,使用mysql数据库

创建一个Java项目,POM文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.zccoder</groupId>
  <artifactId>myspringdata</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>
    <!-- spring-data-jpa -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.11.3.RELEASE</version>
    </dependency>
   <dependency>
      <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>5.2.10.Final</version>
  </dependency>
    <!-- mysql -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <!-- junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

完成后的项目结构图:

clipboard.png

2-3 JDBCUtil开发

开发JDBCUtil工具类

获取Connection,关闭Connection、Statement、ResultSet
注意事项:配置的属性放置配置文件中,然后通过代码的方式将配置文件中的数据加载进来即可。

代码示例:

package com.myimooc.springdata.jdbc.util;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC工具类:
 * 1)获取Connection
 * 2)释放资源
 * Created by ZC on 2017/4/24.
 */
public class JDBCUtils {

    /**
     * 获取Connection
     * @return 所获得到的JDBC的Connection
     */
    public static Connection getConnection() throws Exception{
        /**
         * 不建议大家把配置硬编码到代码中
         * 最佳实践:配置性的建议写到配置文件中
         * */
//        String url = "jdbc:mysql:///springdata";
//        String username = "root";
//        String password = "root";
//        String dirverClass = "com.mysql.jdbc.Driver";

        InputStream inputStream =  JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
        Properties properties = new Properties();
        properties.load(inputStream);

        String url = properties.getProperty("jdbc.url");
        String username = properties.getProperty("jdbc.username");
        String password = properties.getProperty("jdbc.password");
        String driverClass = properties.getProperty("jdbc.driverClass");

        Class.forName(driverClass);
        Connection connection = DriverManager.getConnection(url,username,password);
        return connection;
    }

    /**
     * 释放DB相关资源
     * @param resultSet
     * @param statement
     * @param connection
     */
    public static void release(ResultSet resultSet, Statement statement,Connection connection){
        if(resultSet != null ){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement != null ){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection != null ){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

2-4 Dao开发

建立对象模型及DAO层开发。

代码演示:

1、对象模型

package com.myimooc.springdata.jdbc.domain;

/**
 * Student实体类
 * Created by ZC on 2017/4/24.
 */
public class Student {
    /** 主键ID */
    private Integer id;
    /** 姓名 */
    private String name;
    /** 年龄 */
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2、DAO接口

package com.myimooc.springdata.jdbc.dao;

import com.myimooc.springdata.jdbc.domain.Student;

import java.util.List;

/**
 * StudentDAO访问接口
 * Created by ZC on 2017/4/24.
 */
public interface StudentDao {
    /**
     * 获取所有学生
     * @return 所有学生
     */
    List<Student> listStudent();

    /**
     * 添加一个学生
     * @param student 待添加的学生
     */
    void saveStudent(Student student);
}

3、DAO实现

package com.myimooc.springdata.jdbc.dao.impl;

import com.myimooc.springdata.jdbc.dao.StudentDao;
import com.myimooc.springdata.jdbc.domain.Student;
import com.myimooc.springdata.jdbc.util.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * StudentDAO访问接口实现类:通过最原始的JDBC的方式操作
 * Created by ZC on 2017/4/24.
 */
public class StudentDaoImpl implements StudentDao {

    public List<Student> listStudent() {
        List<Student> studentList = new ArrayList<Student>();

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        String sql = "select id,name,age from student";
        try {
            connection = JDBCUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();

            while(resultSet.next()){
                Integer id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                Integer age = resultSet.getInt("age");

                Student student = new Student();
                student.setId(id);
                student.setName(name);
                student.setAge(age);

                studentList.add(student);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(resultSet,preparedStatement,connection);
        }
        return studentList;
    }

    public void saveStudent(Student student) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        String sql = "insert into student(name,age) values(?,?)";
        try {
            connection = JDBCUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,student.getName());
            preparedStatement.setInt(2,student.getAge());

            preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(resultSet,preparedStatement,connection);
        }
    }
}

4、单元测试

package com.myimooc.springdata.jdbc.dao;

import com.myimooc.springdata.jdbc.dao.impl.StudentDaoImpl;
import com.myimooc.springdata.jdbc.domain.Student;
import org.junit.Test;

import java.util.List;

/**
 * StudentDao 单元测试类
 * Created by ZC on 2017/4/24.
 */
public class StudentDaoImplTest {

    @Test
    public void listStudentTest(){
        StudentDao studentDao = new StudentDaoImpl();

        List<Student>  studentList = studentDao.listStudent();
        for(Student student : studentList){
            System.out.println(student.toString());
        }
    }

    @Test
    public void saveStudentTest(){
        StudentDao studentDao = new StudentDaoImpl();

        Student student = new Student();
        student.setName("test");
        student.setAge(30);

        studentDao.saveStudent(student);
    }

}

2-5 使用JdbcTemplate

Spring JdbcTemplate

添加maven依赖
DataSource & JdbcTemplate注入
Test Case

代码演示:

1、创建DB配置文件

jdbc.url = jdbc:mysql:///springdata
jdbc.username = root
jdbc.password = root
jdbc.driverClass = com.mysql.jdbc.Driver

2、创建配置文件类

package com.myimooc.springdata.jdbctemplate.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * 配置参数类
 * Created by ZC on 2017/4/24.
 */
@PropertySource(value="classpath:db.properties")
@Component
public class Properties {
    @Value("${jdbc.driverClass}")
    private String jdbcDriverClass;
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUser;
    @Value("${jdbc.password}")
    private String jdbcPassword;

    @Override
    public String toString() {
        return "Properties{" +
                "jdbcDriverClass='" + jdbcDriverClass + '\'' +
                ", jdbcUrl='" + jdbcUrl + '\'' +
                ", jdbcUser='" + jdbcUser + '\'' +
                ", jdbcPassword='" + jdbcPassword + '\'' +
                '}';
    }

    public String getJdbcDriverClass() {
        return jdbcDriverClass;
    }

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public String getJdbcUser() {
        return jdbcUser;
    }

    public String getJdbcPassword() {
        return jdbcPassword;
    }
}

3、配置DataSource、JdbcTemplate和Spring注解扫描

package com.myimooc.springdata.jdbctemplate.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

/**
 * Created by ZC on 2017/4/24.
 */
@Configuration
@ComponentScan("com.myimooc.springdata.jdbctemplate")
public class SpringConfig {

    @Autowired
    private Properties properties;

    @Bean
    DriverManagerDataSource getDriverManagerDataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(properties.getJdbcDriverClass());
        driverManagerDataSource.setUrl(properties.getJdbcUrl());
        driverManagerDataSource.setUsername(properties.getJdbcUser());
        driverManagerDataSource.setPassword(properties.getJdbcPassword());
        return driverManagerDataSource;
    }

    @Bean
    JdbcTemplate getJdbcTemplate(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(getDriverManagerDataSource());
        return jdbcTemplate;
    }
}

4、编写实体类

package com.myimooc.springdata.jdbctemplate.domain;

/**
 * Student实体类
 * Created by ZC on 2017/4/24.
 */
public class Student {
    /** 主键ID */
    private Integer id;
    /** 姓名 */
    private String name;
    /** 年龄 */
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

5、DAO接口

package com.myimooc.springdata.jdbctemplate.dao;

import com.myimooc.springdata.jdbctemplate.domain.Student;

import java.util.List;

/**
 * StudentDAO访问接口
 * Created by ZC on 2017/4/24.
 */
public interface StudentDao {
    /**
     * 获取所有学生
     * @return 所有学生
     */
    List<Student> listStudent();

    /**
     * 添加一个学生
     * @param student 待添加的学生
     */
    void saveStudent(Student student);
}

6、DAO实现

package com.myimooc.springdata.jdbctemplate.dao.impl;

import com.myimooc.springdata.jdbctemplate.dao.StudentDao;
import com.myimooc.springdata.jdbctemplate.domain.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * StudentDAO访问接口实现类:通过 JdbcTemplate 的方式操作
 * Created by ZC on 2017/4/24.
 */
@Repository
public class StudentDaoImpl implements StudentDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<Student> listStudent() {
        List<Student> studentList = new ArrayList<Student>();
        String sql = "select id, name, age from student";
        List<Map<String,Object>>  mapList = jdbcTemplate.queryForList(sql);
        for (Map<String,Object> mapTemp : mapList) {
            Integer id = Integer.parseInt(mapTemp.get("id").toString());
            String name = mapTemp.get("name").toString();
            Integer age = Integer.parseInt(mapTemp.get("age").toString());

            Student student = new Student();
            student.setId(id);
            student.setName(name);
            student.setAge(age);

            studentList.add(student);
        }
        return studentList;
    }

    public void saveStudent(Student student) {
        String sql = "insert into student(name, age) value(?,?)";
        jdbcTemplate.update(sql,student.getName(),student.getAge());
    }
}

7、单元测试类

package com.myimooc.springdata.jdbctemplate;

import com.myimooc.springdata.jdbctemplate.config.SpringConfig;
import com.myimooc.springdata.jdbctemplate.dao.StudentDao;
import com.myimooc.springdata.jdbctemplate.domain.Student;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;
import java.util.List;

/**
 *  使用 JdbcTemplate 实现 StudentDao 单元测试类
 * Created by ZC on 2017/4/24.
 */
public class StudentDaoTest {

    private ApplicationContext ctx = null;
    private StudentDao studentDao;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        studentDao = ctx.getBean(StudentDao.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void listStudentTest(){
        List<Student> studentList = studentDao.listStudent();
        for (Student student : studentList){
            System.out.println(student.toString());
        }
    }

    @Test
    public void saveTest(){
        Student student = new Student();
        student.setName("test-spring-jdbcTemplate");
        student.setAge(25);
        studentDao.saveStudent(student);
    }

}

2-6 弊端分析

弊端分析

DAO里面代码量太多
DAO的实现有很多重复代码
开发分页和其它功能,需要重新进行封装

第三章:Spring Data快速入门

3-1 开发环境搭建

Spring Data JPA快速起步

开发环境搭建
Spring Data JPA HelloWorld开发

代码演示:

1、创建DB配置文件

jdbc.url = jdbc:mysql:///springdata
jdbc.username = root
jdbc.password = root
jdbc.driverClass = com.mysql.jdbc.Driver

2、创建配置文件类

package com.myimooc.springdata.jpa.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * Created by ZC on 2017/4/24.
 */
@PropertySource(value="classpath:db.properties")
@Component
public class PropertiesConfig {
    @Value("${jdbc.driverClass}")
    private String jdbcDriverClass;
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUser;
    @Value("${jdbc.password}")
    private String jdbcPassword;

    @Override
    public String toString() {
        return "Properties{" +
                "jdbcDriverClass='" + jdbcDriverClass + '\'' +
                ", jdbcUrl='" + jdbcUrl + '\'' +
                ", jdbcUser='" + jdbcUser + '\'' +
                ", jdbcPassword='" + jdbcPassword + '\'' +
                '}';
    }

    public String getJdbcDriverClass() {
        return jdbcDriverClass;
    }

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public String getJdbcUser() {
        return jdbcUser;
    }

    public String getJdbcPassword() {
        return jdbcPassword;
    }
}

3、配置TransactionManager、EntityManagerFactory和Spring自动扫描注入

package com.myimooc.springdata.jpa.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.Properties;

/**
 * Spring配置类
 * Created by ZC on 2017/4/24.
 */
// 声明为配置类
@Configuration
// 启用事务管理
@EnableTransactionManagement
// 启用自动扫描继承 JpaRepository 接口的类。
// 注意,此注解需要配置 entityManagerFactory 和 transactionManager
// 方式一:定义获取Bean方法名为 entityManagerFactory 和 transactionManager
// 方式二:配置 @EnableJpaRepositories注解的 entityManagerFactoryRef 属性 为自定义获取Bean的方法名。
@EnableJpaRepositories(basePackages = "com.myimooc.springdata.jpa")
// 启用自动扫描 @Component 注解的Bean
@ComponentScan(basePackages = "com.myimooc.springdata.jpa")
public class SpringConfig{

    @Autowired
    private PropertiesConfig propertiesConfig;

    /**
     * 配置数据源
     * @return
     */
    @Bean
    public DriverManagerDataSource dataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(propertiesConfig.getJdbcDriverClass());
        driverManagerDataSource.setUrl(propertiesConfig.getJdbcUrl());
        driverManagerDataSource.setUsername(propertiesConfig.getJdbcUser());
        driverManagerDataSource.setPassword(propertiesConfig.getJdbcPassword());
        return driverManagerDataSource;
    }


    /**
     * 配置事务管理器 JpaTransactionManager
     * @return
     */
    @Bean(name="transactionManager")
    public PlatformTransactionManager transactionManager(){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setDataSource(this.dataSource());
        transactionManager.setEntityManagerFactory(this.entityManagerFactory().getObject());
        return transactionManager;
//        return new DataSourceTransactionManager(this.dataSource());
//        return new JpaTransactionManager(this.entityManagerFactory().getObject());
    }

    /**
     * 配置JPA的 EntityManagerFactory
     * @return
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource());

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);
        jpaVendorAdapter.setDatabase(Database.MYSQL);
        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);

        entityManagerFactory.setPackagesToScan("com.myimooc.springdata.jpa");

        Properties jpaProperties = new Properties();
//        jpaProperties.setProperty("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy");
        jpaProperties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect");
        jpaProperties.setProperty("hibernate.show_sql","true");
        jpaProperties.setProperty("hibernate.format_sql","true");
        jpaProperties.setProperty("hibernate.hbm2ddl.auto","update");

        entityManagerFactory.setJpaProperties(jpaProperties);

        return entityManagerFactory;
    }

}

4、编写实体类:Employee

package com.myimooc.springdata.jpa.domain;

import javax.persistence.*;

/**
 * 雇员:先开发实体类,然后自动生成实体表
 * Created by ZC on 2017/4/24.
 */
@Entity
@Table(name = "test_employee")
public class Employee {
    @Id
    @GeneratedValue
    private Integer id;

    @Column(length = 20)
    private String name;

    private Integer age;

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    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 Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

3-2 起步程序开发

代码演示:

1、编写EmployeeRepository接口

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 使用 Repository 接口
 * Created by ZC on 2017/4/25.
 */
// 方式二:使用 @RepositoryDefinition 注解
//  @RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
public interface EmployeeRepository extends Repository<Employee,Integer> {//方式一:继承 Repository 接口

    /**
     * 获取雇员对象通过名称
     * @param name
     * @return
     */
    Employee findByName(String name);
}

2、编写单元测试类:EmployeeRepositoryTest

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeeRepository;
import com.myimooc.springdata.jpa.service.EmployeeService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import java.util.ArrayList;
import java.util.List;

/**
 * EmployeeRepository单元测试类
 * Created by ZC on 2017/4/24.
 */
public class EmployeeRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeeRepository employeeRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeRepository = ctx.getBean(EmployeeRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void entityManageFactoryTest(){
        LocalContainerEntityManagerFactoryBean entityManagerFactory = (LocalContainerEntityManagerFactoryBean)ctx.getBean(LocalContainerEntityManagerFactoryBean.class);
        Assert.assertNotNull(entityManagerFactory);
    }

    @Test
    public void findByNameTest(){
        System.out.println(employeeRepository);
        Employee employee = employeeRepository.findByName("cc");
        if( null == employee){
            System.out.println("查询数据为空");
        }else{
            System.out.println(employee.toString());
        }
    }
}

Repository

Repository:Spring Data核心类
RepositoryDefinition:使用该注解进行配置
Repository Query Specification:查询时,方法命名不能乱写
Query Annotation:使用该注解,可以实现原生SQL查询
Update/Delete/Transaction:更新、删除操作,支持事务

Repository Hierarchy

CrudRepository:内置了新增、更新、删除、查询方法
PagingAndSortingRespository:分页和排序
JpaRepository
JpaSpecificationExcutor

第四章:Spring Data JPA进阶

4-1 关于Repository接口

Repository接口详解

Repository接口是Spring Data的核心接口,不提供任何方法
public interface Repository<T, ID extends Serializable>{}
@RepositoryDefinition注解的使用

Repository类的定义:

1)Repository是一个空接口,标记接口。没有包含方法声明的接口
2)如果我们定义的接口EmployeeRepository extends Repository,会被Spring管理。
    如果我们自己的接口没有extends Repository,运行时会报错,没有这个Bean。

4-2 Repository子接口详解

Repository子接口详解

CrudRepository:继承Repository,实现了CRUD相关的方法
PagingAndSortingRepository:继承CrudRepository,实现了分页排序相关的方法
JpaRepository:继承PagingAndSortingRepositor,实现JPA规范相关的方法

4-3 查询方法定义规则和使用

Repository中查询方法定义规则和使用

了解Spring Data中查询方法名称的定义规则
使用Spring Data完成复杂查询方法名称的命名

查询方法定义规则

clipboard.png

clipboard.png

代码演示:

1、在EmployeeRepository接口编写以下代码

    // 使用JPA规范查询

    // where name like ?% and age < ?
    List<Employee> findByNameStartingWithAndAgeLessThan(String name,Integer age);

    // where name like %? and age < ?
    List<Employee> findByNameEndingWithAndAgeLessThan(String name,Integer age);

    // where name in (?,?...) or age < ?
    List<Employee> findByNameInOrAgeLessThan(List<String> name,Integer age);

    // where name in (?,?...) and age < ?
    List<Employee> findByNameInAndAgeLessThan(List<String> name,Integer age);

2、在EmployeeRepositoryTest单元测试类进行测试

@Test
    public void findByNameStartingWithAndAgeLessThanTest(){
        System.out.println(employeeRepository);
        List<Employee> employees = employeeRepository.findByNameStartingWithAndAgeLessThan("test",22);

        if( null != employees){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void findByNameEndingWithAndAgeLessThanTest(){
        System.out.println(employeeRepository);
        List<Employee> employees = employeeRepository.findByNameEndingWithAndAgeLessThan("6",23);

        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void findByNameInOrAgeLessThanTest(){
        List<String> names = new ArrayList<String>();
        names.add("test1");
        names.add("test2");
        names.add("test3");
        List<Employee> employees = employeeRepository.findByNameInOrAgeLessThan(names,22);

        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void findByNameInAndAgeLessThanTest(){
        List<String> names = new ArrayList<String>();
        names.add("test1");
        names.add("test2");
        names.add("test3");
        List<Employee> employees = employeeRepository.findByNameInAndAgeLessThan(names,22);

        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

对于按照方法命名规则来使用的话,有弊端:

1)方法名比较长:约定大于配置
2)对于一些复杂的查询,是很难实现。

使用@Query注解来解决。

4-4 Query注解使用

Query注解使用

在Respository方法中使用,不需要遵循查询方法命令规则
只需要将@Query定义在Respository中的方法之上即可
命名参数及索引参数的使用
本地查询

代码演示:

1、在EmployeeRepository接口编写以下代码

// 使用@Query注解查询

    /**
     * 自定义查询SQL
     * */
    @Query("select o from Employee o where id=(select max(id) from Employee t1)")
    Employee getEmployeeByMaxId();

    /**
     * 使用占位符进行参数绑定
     * */
    @Query("select o from Employee o where o.name=?1 and o.age=?2")
    List<Employee> listEmployeeByNameAndAge(String name, Integer age);

    /**
     * 使用命名参数进行参数绑定
     * */
    @Query("select o from Employee o where o.name=:name and o.age=:age")
    List<Employee> listEmployeeByNameAndAge2(@Param("name") String name, @Param("age")Integer age);

    /**
     * 自定义查询SQL,like,占位符进行参数绑定
     * */
    @Query("select o from Employee o where o.name like %?1%")
    List<Employee> listEmployeeByLikeName(String name);

    /**
     * 自定义查询SQL,like,命名参数进行参数绑定
     * */
    @Query("select o from Employee o where o.name like %:name%")
    List<Employee> listEmployeeByLikeName2(@Param("name") String name);

    /**
     * 使用原生态SQL查询
     * @return
     */
    @Query(nativeQuery = true,value = "select count(1) from employee")
    long getCount();

2、在EmployeeRepositoryTest单元测试类进行测试

//  使用 @Query 注解查询
    @Test
    public void getEmployeeByMaxIdTest(){

        Employee employee = employeeRepository.getEmployeeByMaxId();

        if( null != employee ){
                System.out.println(employee.toString());
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void listEmployeeByNameAndAgeTest(){
        List<Employee> employees = employeeRepository.listEmployeeByNameAndAge("zhangsan",20);
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void listEmployeeByNameAndAge2Test(){
        List<Employee> employees = employeeRepository.listEmployeeByNameAndAge2("zhangsan",20);
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void listEmployeeByLikeNameTest(){
        List<Employee> employees = employeeRepository.listEmployeeByLikeName("test1");
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void listEmployeeByLikeName2Test(){
        List<Employee> employees = employeeRepository.listEmployeeByLikeName2("test");
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("查询数据为空");
        }
    }

    @Test
    public void getCountTest(){
        long count = employeeRepository.getCount();
        System.out.println(count);
    }

4-5 更新操作整合事务使用

更新及删除操作整合事务的使用

@Modifying注解使用
@Modifying结合@Query注解执行更新操作
@Transaction在Spring Data中的使用

事务在Spring data中的使用:

1)事务一般是在Service层
2)@Query、@Modifying、@Transaction的综合使用

代码演示:

1、基于javaconfig在SpringConfig类进行事务配置

package com.myimooc.springdata.jpa.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.Properties;

/**
 * Spring配置类
 * Created by ZC on 2017/4/24.
 */
// 声明为配置类
@Configuration
// 启用事务管理
@EnableTransactionManagement
// 启用自动扫描继承 JpaRepository 接口的类。
// 注意,此注解需要配置 entityManagerFactory 和 transactionManager
// 方式一:定义获取Bean方法名为 entityManagerFactory 和 transactionManager
// 方式二:配置 @EnableJpaRepositories注解的 entityManagerFactoryRef 属性 为自定义获取Bean的方法名。
@EnableJpaRepositories(basePackages = "com.myimooc.springdata.jpa")
// 启用自动扫描 @Component 注解的Bean
@ComponentScan(basePackages = "com.myimooc.springdata.jpa")
public class SpringConfig{

    @Autowired
    private PropertiesConfig propertiesConfig;

    /**
     * 配置数据源
     * @return
     */
    @Bean
    public DriverManagerDataSource dataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(propertiesConfig.getJdbcDriverClass());
        driverManagerDataSource.setUrl(propertiesConfig.getJdbcUrl());
        driverManagerDataSource.setUsername(propertiesConfig.getJdbcUser());
        driverManagerDataSource.setPassword(propertiesConfig.getJdbcPassword());
        return driverManagerDataSource;
    }


    /**
     * 配置事务管理器 JpaTransactionManager
     * @return
     */
    @Bean(name="transactionManager")
    public PlatformTransactionManager transactionManager(){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setDataSource(this.dataSource());
        transactionManager.setEntityManagerFactory(this.entityManagerFactory().getObject());
        return transactionManager;
//        return new DataSourceTransactionManager(this.dataSource());
//        return new JpaTransactionManager(this.entityManagerFactory().getObject());
    }

    /**
     * 配置JPA的 EntityManagerFactory
     * @return
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource());

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);
        jpaVendorAdapter.setDatabase(Database.MYSQL);
        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);

        entityManagerFactory.setPackagesToScan("com.myimooc.springdata.jpa");

        Properties jpaProperties = new Properties();
//        jpaProperties.setProperty("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy");
        jpaProperties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect");
        jpaProperties.setProperty("hibernate.show_sql","true");
        jpaProperties.setProperty("hibernate.format_sql","true");
        jpaProperties.setProperty("hibernate.hbm2ddl.auto","update");

        entityManagerFactory.setJpaProperties(jpaProperties);

        return entityManagerFactory;
    }

}

2、在EmployeeRepository接口编写以下代码

    // 更新数据
    @Transactional
    @Modifying
    @Query("update Employee o set o.age = :age where o.id = :id")
    void updateAgeById(@Param("id")Integer id,@Param("age")Integer age);

3、定义Service层,实际开发中,需要定义接口,这里为了演示方便,直接使用类。

package com.myimooc.springdata.jpa.service;

import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeeCrudRepository;
import com.myimooc.springdata.jpa.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


/**
 * Created by ZC on 2017/4/25.
 */
@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private EmployeeCrudRepository employeeCrudRepository;

    @Transactional
    public void updateAgeById(Integer id, Integer age){
        this.employeeRepository.updateAgeById(id,age);
    };

    @Transactional
    public void save(List<Employee> employees){
        this.employeeCrudRepository.save(employees);
    }
}

4、编写EmployeeService单元测试类

package com.myimooc.springdata.jpa.service;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.repository.EmployeeRepository;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * EmployeeService单元测试类
 * Created by ZC on 2017/4/25.
 */
public class EmployeeServiceTest {

    private ApplicationContext ctx = null;
    private EmployeeService employeeService = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeService = ctx.getBean(EmployeeService.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void transactionManagerTest(){
        PlatformTransactionManager transactionManager = (PlatformTransactionManager)ctx.getBean(PlatformTransactionManager.class);
        Assert.assertNotNull(transactionManager);
    }

    // 更新操作

    @Test
    public void updateAgeByIdTest(){
        employeeService.updateAgeById(1,55);
    }

}

第五章:Spring Data JPA高级

5-1 CrudRepository接口使用详解

CrudRepository接口使用详解

save(entity):保存一个实体
save(entities):保存多个实体
findOne(id):找到一个对象
exists(id):根据ID判断对象是否存在
findAll():找到所有实体对象
delete(id):根据ID删除实体对象
delete(entity):根据实体对象删除实体对象
delete(entities):删除多个实体对象
deleteAll():删除所有实体对象

代码演示:

1、编写EmployeeCrudRepository接口

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.repository.CrudRepository;

/**
 * 使用 CrudRepository 接口
 * Created by ZC on 2017/4/26.
 */
public interface EmployeeCrudRepository extends CrudRepository<Employee,Integer>{

}

2、编写EmployeeCrudRepositoryTest单元测试类

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * EmployeeRepository单元测试类
 * Created by ZC on 2017/4/24.
 */
public class EmployeeCrudRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeeCrudRepository employeeCrudRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeCrudRepository = ctx.getBean(EmployeeCrudRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void saveTest(){
        List<Employee> employees = new ArrayList<Employee>();
        Employee employee = null;
        for(int i=0;i<100;i++){
            employee = new Employee();
            employee.setName("test"+i);
            employee.setAge(100 - i);
            employees.add(employee);
        }
        employeeCrudRepository.save(employees);
    }

}

5-2 PagingAndSortingRespository接口使用详解

PagingAndSortingRespository接口使用详解

该接口包含分页和排序的功能
带排序的查询:findAll(Sort sort)
带排序的分页查询:findAll(Pageable pageable)

代码演示:

1、编写EmployeePagingAndSortingRepository接口

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * 使用 PagingAndSortingRepository 实现分页和排序功能
 * Created by ZC on 2017/4/26.
 */
public interface EmployeePagingAndSortingRepository extends PagingAndSortingRepository<Employee,Integer> {
}

2、编写EmployeePagingAndSortingRepositoryTest单元测试类

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeePagingAndSortingRepository;
import com.myimooc.springdata.jpa.service.EmployeeService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import java.util.ArrayList;
import java.util.List;

/**
 * PagingAndSortingRepository 单元测试类
 * Created by ZC on 2017/4/26.
 */
public class EmployeePagingAndSortingRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeePagingAndSortingRepository employeePagingAndSortingRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeePagingAndSortingRepository = ctx.getBean(EmployeePagingAndSortingRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    /**
     * 分页功能测试
     */
    @Test
    public void pageTest(){
        // page: index是从0开始的,不是从1开始的
        Pageable pageable = new PageRequest(0,9);
        Page<Employee> employeePage = employeePagingAndSortingRepository.findAll(pageable);

        System.out.println("查询的总页数:"+employeePage.getTotalPages());
        System.out.println("查询的总记录数:"+employeePage.getTotalElements());
        System.out.println("查询的当前第几页:"+(employeePage.getNumber() + 1));
        System.out.println("查询的当前页面的集合:"+employeePage.getContent());
        System.out.println("查询的当前页面的记录数:"+employeePage.getNumberOfElements());

    }

    /**
     * 分页和排序功能测试
     */
    @Test
    public void pageAndSort(){
        Sort.Order order = new Sort.Order(Sort.Direction.ASC,"id");
        Sort sort = new Sort(order);
        // page: index是从0开始的,不是从1开始的
        Pageable pageable = new PageRequest(0,5,sort);
        Page<Employee> employeePage = employeePagingAndSortingRepository.findAll(pageable);

        System.out.println("查询的总页数:"+employeePage.getTotalPages());
        System.out.println("查询的总记录数:"+employeePage.getTotalElements());
        System.out.println("查询的当前第几页:"+(employeePage.getNumber() + 1));
        System.out.println("查询的当前页面的集合:"+employeePage.getContent());
        System.out.println("查询的当前页面的记录数:"+employeePage.getNumberOfElements());
    }

}

5-3 JpaRepository接口使用详解

JpaRepository接口使用详解

finaAll:查询所有记录
findAll(Sort sort):查询所有记录并排序
save(entities):保存多个实体对象
fiush:
deleteInBatch(entities):一个批次里面删除那些实体

代码演示:

1、编写EmployeeJpaRepository接口

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * 使用 JpaRepository 接口
 * Created by ZC on 2017/4/26.
 */
public interface EmployeeJpaRepository extends JpaRepository<Employee,Integer> {
}

2、编写EmployeeJpaRepositoryTest单元测试类

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeeJpaRepository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * EmployeeJpaRepository 单元测试类
 * Created by ZC on 2017/4/26.
 */
public class EmployeeJpaRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeeJpaRepository employeeJpaRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeJpaRepository = ctx.getBean(EmployeeJpaRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void findTest(){
        Employee employee = employeeJpaRepository.findOne(99);
        System.out.println("employee"+employee.toString());

        System.out.println("employee(10)"+employeeJpaRepository.exists(10));
        System.out.println("employee(102)"+employeeJpaRepository.exists(102));
    }

}

5-4 JpaSpecificationExecutor接口使用详解

JpaSpecificationExecutor接口使用详解

Specification封装了JPA Criteria查询条件

代码演示:

1、编写EmployeeJpaSpecificationExecutor接口

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

/**
 * 使用 JpaSpecificationExecutor 接口
 * Created by ZC on 2017/4/26.
 */
public interface EmployeeJpaSpecificationExecutor extends JpaRepository<Employee,Integer> ,
        JpaSpecificationExecutor<Employee>{
}

2、编写EmployeeJpaSpecificationExecutorTest单元测试类

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;

/**
 * EmployeeJpaSpecificationExecutor 单元测试类
 * Created by ZC on 2017/4/26.
 */
public class EmployeeJpaSpecificationExecutorTest {

    private ApplicationContext ctx = null;
    private EmployeeJpaSpecificationExecutor employeeJpaSpecificationExecutor = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeJpaSpecificationExecutor = ctx.getBean(EmployeeJpaSpecificationExecutor.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    /**
     * 1、分页
     * 2、排序
     * 3、查询条件:age > 50
     */
    @Test
    public void queryTest(){
        Sort.Order order = new Sort.Order(Sort.Direction.DESC,"id");
        Sort sort = new Sort(order);
        // page: index是从0开始的,不是从1开始的
        Pageable pageable = new PageRequest(0,5,sort);

        /**
         * root : 就是我们要查询的类型 (Employee)
         * query : 添加查询条件
         * cb : 构建 Predicate
         */
        Specification<Employee> specification = new Specification<Employee>() {
            // 查询条件
            public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // root (employee (age))
                Path path = root.get("age");
                return cb.gt(path,50);
            }
        };

        Page<Employee> employeePage = employeeJpaSpecificationExecutor.findAll(specification,pageable);

        System.out.println("查询的总页数:"+employeePage.getTotalPages());
        System.out.println("查询的总记录数:"+employeePage.getTotalElements());
        System.out.println("查询的当前第几页:"+(employeePage.getNumber() + 1));
        System.out.println("查询的当前页面的集合:"+employeePage.getContent());
        System.out.println("查询的当前页面的记录数:"+employeePage.getNumberOfElements());

    }

}

第六章:课程总结

6-4 课程总结

课程总结

Spring Data概览
传统方式访问数据库
Spring Data快速起步
Spring Data JPA进阶
Spring Data JAP高级
查看原文

Async 关注了问题 · 2016-09-30

我想给公司做一个技术分享会,不知道大家有什么推荐的,容易上手的

我想给公司做一个技术分享会,不知道大家有什么推荐的,容易上手的

关注 5 回答 6

Async 回答了问题 · 2016-09-30

我想给公司做一个技术分享会,不知道大家有什么推荐的,容易上手的

shell脚本编程

关注 5 回答 6

Async 关注了问题 · 2016-08-22

python解析html,哪个库好用点?

因为leancloud好像不支持pyquery,所以这个不考虑了,再就是htmlparser好像不是很好用,有推荐的吗

关注 8 回答 6

Async 关注了问题 · 2016-08-17

kafka总是在启动一段时间后自动停止

kafka 总是在启动一段时间后自动关闭,区间大概是 2.3h~3h 之间。
kafka server log 没有错误抛出,log 和正常关闭一模一样。

kafka-server.log:

[2016-01-11 12:15:06,435] INFO Verifying properties (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,489] INFO Property broker.id is overridden to 0 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,489] INFO Property host.name is overridden to 172.16.1.22 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,490] INFO Property log.cleaner.enable is overridden to false (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,490] INFO Property log.dirs is overridden to /data/www/wifiin/logs/kafka (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,490] INFO Property log.retention.check.interval.ms is overridden to 300000 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,491] INFO Property log.retention.hours is overridden to 168 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,491] INFO Property log.segment.bytes is overridden to 1073741824 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,491] INFO Property num.io.threads is overridden to 8 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,491] INFO Property num.network.threads is overridden to 3 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,492] INFO Property num.partitions is overridden to 1 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,492] INFO Property num.recovery.threads.per.data.dir is overridden to 1 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,492] INFO Property port is overridden to 9092 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,493] INFO Property socket.receive.buffer.bytes is overridden to 102400 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,493] INFO Property socket.request.max.bytes is overridden to 104857600 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,493] INFO Property socket.send.buffer.bytes is overridden to 102400 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,493] INFO Property zookeeper.connect is overridden to 127.0.0.1:2181 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,494] INFO Property zookeeper.connection.timeout.ms is overridden to 6000 (kafka.utils.VerifiableProperties)
[2016-01-11 12:15:06,550] INFO [Kafka Server 0], starting (kafka.server.KafkaServer)
[2016-01-11 12:15:06,553] INFO [Kafka Server 0], Connecting to zookeeper on 127.0.0.1:2181 (kafka.server.KafkaServer)
[2016-01-11 12:15:06,568] INFO Starting ZkClient event thread. (org.I0Itec.zkclient.ZkEventThread)
[2016-01-11 12:15:06,579] INFO Client environment:zookeeper.version=3.4.6-1569965, built on 02/20/2014 09:09 GMT (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,579] INFO Client environment:host.name=wifiin-analysis-22 (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,579] INFO Client environment:java.version=1.7.0_40 (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,579] INFO Client environment:java.vendor=Oracle Corporation (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,579] INFO Client environment:java.home=/usr/local/java/jdk1.7.0_40/jre (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,579] INFO Client environment:java.class.path=.:/usr/local/java/latest//lib/dt.jar:/usr/local/java/latest//lib/tools.jar:/usr/local/kafka/bin/../core/build/dependant-libs-2.10.4*/*.jar:/usr/local/kafka/bin/../examples/build/libs//kafka-examples*.jar:/usr/local/kafka/bin/../contrib/hadoop-consumer/build/libs//kafka-hadoop-consumer*.jar:/usr/local/kafka/bin/../contrib/hadoop-producer/build/libs//kafka-hadoop-producer*.jar:/usr/local/kafka/bin/../clients/build/libs/kafka-clients*.jar:/usr/local/kafka/bin/../libs/jopt-simple-3.2.jar:/usr/local/kafka/bin/../libs/kafka_2.9.1-0.8.2.1.jar:/usr/local/kafka/bin/../libs/kafka_2.9.1-0.8.2.1-javadoc.jar:/usr/local/kafka/bin/../libs/kafka_2.9.1-0.8.2.1-scaladoc.jar:/usr/local/kafka/bin/../libs/kafka_2.9.1-0.8.2.1-sources.jar:/usr/local/kafka/bin/../libs/kafka_2.9.1-0.8.2.1-test.jar:/usr/local/kafka/bin/../libs/kafka-clients-0.8.2.1.jar:/usr/local/kafka/bin/../libs/log4j-1.2.16.jar:/usr/local/kafka/bin/../libs/lz4-1.2.0.jar:/usr/local/kafka/bin/../libs/metrics-core-2.2.0.jar:/usr/local/kafka/bin/../libs/scala-library-2.9.1.jar:/usr/local/kafka/bin/../libs/slf4j-api-1.7.6.jar:/usr/local/kafka/bin/../libs/slf4j-log4j12-1.6.1.jar:/usr/local/kafka/bin/../libs/snappy-java-1.1.1.6.jar:/usr/local/kafka/bin/../libs/zkclient-0.3.jar:/usr/local/kafka/bin/../libs/zookeeper-3.4.6.jar:/usr/local/kafka/bin/../core/build/libs/kafka_2.10*.jar (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,579] INFO Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:java.io.tmpdir=/tmp (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:java.compiler=<NA> (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:os.name=Linux (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:os.arch=amd64 (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:os.version=2.6.32-573.3.1.el6.x86_64 (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:user.name=root (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:user.home=/root (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,580] INFO Client environment:user.dir=/usr/local/kafka (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,581] INFO Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=6000 watcher=org.I0Itec.zkclient.ZkClient@52d73384 (org.apache.zookeeper.ZooKeeper)
[2016-01-11 12:15:06,609] INFO Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error) (org.apache.zookeeper.ClientCnxn)
[2016-01-11 12:15:06,614] INFO Socket connection established to 127.0.0.1/127.0.0.1:2181, initiating session (org.apache.zookeeper.ClientCnxn)
[2016-01-11 12:15:06,661] INFO Session establishment complete on server 127.0.0.1/127.0.0.1:2181, sessionid = 0x15210b1e3051357, negotiated timeout = 6000 (org.apache.zookeeper.ClientCnxn)
[2016-01-11 12:15:06,664] INFO zookeeper state changed (SyncConnected) (org.I0Itec.zkclient.ZkClient)
[2016-01-11 12:15:06,915] INFO Loading logs. (kafka.log.LogManager)
[2016-01-11 12:15:07,021] INFO Completed load of log sdkLog-0 with log end offset 209376831 (kafka.log.Log)
[2016-01-11 12:15:07,039] INFO Logs loading complete. (kafka.log.LogManager)
[2016-01-11 12:15:07,040] INFO Starting log cleanup with a period of 300000 ms. (kafka.log.LogManager)
[2016-01-11 12:15:07,044] INFO Starting log flusher with a default period of 9223372036854775807 ms. (kafka.log.LogManager)
[2016-01-11 12:15:17,096] INFO Awaiting socket connections on 172.16.1.22:9092. (kafka.network.Acceptor)
[2016-01-11 12:15:17,097] INFO [Socket Server on Broker 0], Started (kafka.network.SocketServer)
[2016-01-11 12:15:17,195] INFO Will not load MX4J, mx4j-tools.jar is not in the classpath (kafka.utils.Mx4jLoader$)
[2016-01-11 12:15:17,234] INFO 0 successfully elected as leader (kafka.server.ZookeeperLeaderElector)
[2016-01-11 12:15:17,500] INFO Registered broker 0 at path /brokers/ids/0 with address 172.16.1.22:9092. (kafka.utils.ZkUtils$)
[2016-01-11 12:15:17,502] INFO New leader is 0 (kafka.server.ZookeeperLeaderElector$LeaderChangeListener)
[2016-01-11 12:15:17,515] INFO [Kafka Server 0], started (kafka.server.KafkaServer)
[2016-01-11 12:15:17,795] INFO [ReplicaFetcherManager on broker 0] Removed fetcher for partitions [sdkLog,0] (kafka.server.ReplicaFetcherManager)
[2016-01-11 12:15:17,856] INFO [ReplicaFetcherManager on broker 0] Removed fetcher for partitions [sdkLog,0] (kafka.server.ReplicaFetcherManager)
[2016-01-11 14:47:41,816] INFO [Kafka Server 0], shutting down (kafka.server.KafkaServer)
[2016-01-11 14:47:41,818] INFO [Kafka Server 0], Starting controlled shutdown (kafka.server.KafkaServer)
[2016-01-11 14:47:41,981] INFO [Kafka Server 0], Controlled shutdown succeeded (kafka.server.KafkaServer)
[2016-01-11 14:47:41,983] INFO Closing socket connection to /172.16.1.22. (kafka.network.Processor)
[2016-01-11 14:47:41,984] INFO [Socket Server on Broker 0], Shutting down (kafka.network.SocketServer)
[2016-01-11 14:47:41,989] INFO [Socket Server on Broker 0], Shutdown completed (kafka.network.SocketServer)
[2016-01-11 14:47:41,991] INFO [Kafka Request Handler on Broker 0], shutting down (kafka.server.KafkaRequestHandlerPool)
[2016-01-11 14:47:41,994] INFO [Kafka Request Handler on Broker 0], shut down completely (kafka.server.KafkaRequestHandlerPool)
[2016-01-11 14:47:42,267] INFO [Replica Manager on Broker 0]: Shut down (kafka.server.ReplicaManager)
[2016-01-11 14:47:42,267] INFO [ReplicaFetcherManager on broker 0] shutting down (kafka.server.ReplicaFetcherManager)
[2016-01-11 14:47:42,269] INFO [ReplicaFetcherManager on broker 0] shutdown completed (kafka.server.ReplicaFetcherManager)
[2016-01-11 14:47:42,314] INFO [Replica Manager on Broker 0]: Shut down completely (kafka.server.ReplicaManager)
[2016-01-11 14:47:42,315] INFO Shutting down. (kafka.log.LogManager)
[2016-01-11 14:47:42,376] INFO Shutdown complete. (kafka.log.LogManager)
[2016-01-11 14:47:42,384] INFO Terminate ZkClient event thread. (org.I0Itec.zkclient.ZkEventThread)
[2016-01-11 14:47:42,396] INFO Session: 0x15210b1e3051357 closed (org.apache.zookeeper.ZooKeeper)
[2016-01-11 14:47:42,396] INFO EventThread shut down (org.apache.zookeeper.ClientCnxn)
[2016-01-11 14:47:42,396] INFO [Kafka Server 0], shut down completed (kafka.server.KafkaServer)

一开始我以为是 centos 的 OOM Killer 关了它,但是当我改了 oom_score 之后依旧不行。而且在/val/log/message 里面没有找的相关操作的 log。
我现在应该做些什么能修复他,或者进一步的确定错误原因?

万分感谢!


修改与 2016-01-18:

经过查看 kafka 的启动脚本,上周尝试使用

bin/kafka-server-start.sh -daemon ./config/server.properties

进行启动,到现在为止 kafka 还在正常运行。
和不加 -daemon 区别在于:

bin/kafka-run-class.sh

# Launch mode
if [ "x$DAEMON_MODE" = "xtrue" ]; then
  #加 daemon 会使用该命令
  nohup $JAVA $KAFKA_HEAP_OPTS $KAFKA_JVM_PERFORMANCE_OPTS $KAFKA_GC_LOG_OPTS $KAFKA_JMX_OPTS $KAFKA_LOG4J_OPTS -cp $CLASSPATH $KAFKA_OPTS "$@" > "$CONSOLE_OUTPUT_FILE" 2>&1 < /dev/null &
else
  #不加时使用的命令
  exec $JAVA $KAFKA_HEAP_OPTS $KAFKA_JVM_PERFORMANCE_OPTS $KAFKA_GC_LOG_OPTS $KAFKA_JMX_OPTS $KAFKA_LOG4J_OPTS -cp $CLASSPATH $KAFKA_OPTS "$@"
fi

至于为什么以守护进程模式启动 ok。 这个原因还没有找到

关注 6 回答 3

Async 回答了问题 · 2016-06-30

Java 异步http请求。

可以发送完请求后释放连接和资源,让对方处理完后回调你的接口

关注 4 回答 2

认证与成就

  • 获得 9 次点赞
  • 获得 3 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 3 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2014-07-24
个人主页被 232 人浏览