您的位置:首页 > 大数据 > 人工智能

AiSell智能销售系统1

2020-02-07 15:08 183 查看

AiSell智能销售系统

一个简单的项目 基于(Spring+SpringDataJPA+SpringMVC+EasyUI+Maven),欢迎游客们慢慢跟着我来一起做!
注意:
项目部署在IDEA软件,并且TomCat也部署了的。
使用我准备好的数据库表:。。。(博客无法上传sql文件。需要联系我Q:1719099381)

项目的第一个阶段

#####项目第一天

1 在pom.xml里导包(记住需要联网)

<?xml version="1.0" encoding="UTF-8"?>

<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>cn.itsource</groupId>
<artifactId>aisell</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>aisell Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.version>4.2.5.RELEASE</org.springframework.version>
<org.hibernate.version>4.3.8.Final</org.hibernate.version>
<spring-data-jpa.version>1.9.0.RELEASE</spring-data-jpa.version>
<com.fasterxml.jackson.version>2.5.0</com.fasterxml.jackson.version>
<org.slf4j.version>1.6.1</org.slf4j.version>
</properties>
<dependencies>
<!-- Spring的支持包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- 上下文支持包(帮我们集成:模板,邮件,任务调度...) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<!-- 引入web前端的支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- SpringMCV上传需要用到io包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 文件上传用到的包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<!-- SpringMVC的json支持包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<!-- hibernate的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${org.hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${org.hibernate.version}</version>
</dependency>
<!-- SpringDataJpa的支持包 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring-data-jpa.version}</version>
</dependency>
<!-- SpringData的擴展包 -->
<dependency>
<groupId>com.github.wenhao</groupId>
<artifactId>jpa-spec</artifactId>
<version>3.1.1</version>
<!-- 把所有的依賴都去掉 -->
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--lang3:工具包 java.lang.-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<!-- 測試包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!-- 这个scope 只能作用在编译和测试时,同时没有传递性。表示在运行的时候不添加此jar文件 -->
<scope>provided</scope>
</dependency>
<!-- 日志文件 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<!-- 代码生成器模版技术  -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.6</version>
</dependency>
<!-- shiro(权限框架)的支持包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.4.0</version>
<type>pom</type>
</dependency>
<!-- shiro与Spring的集成包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!-- poi(操作办公软件)支持的jar包 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<!-- 图片压缩功能 -->
<!-- 缩略图 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.6</version>
</dependency>
<!-- 定时调度 -->
<dependency>
<groupId>quartz</groupId>
<artifactId>quartz</artifactId>
<version>1.5.2</version>
</dependency>
<!-- 邮件支持 -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
</dependency>
</dependencies>

<build>
<finalName>aisell</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.15.v20140411</version>
<configuration>
<stopPort>9966</stopPort>
<stopKey>foo</stopKey>
<webAppConfig>
<contextPath>/</contextPath>
</webAppConfig>
</configuration>
</plugin>
</plugins>
</build>
</project>

2.集成SpringDataJpa

2.1准备jdbc.propeties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///pps
jdbc.username=root
jdbc.password=123456

2.2 准备applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
">
<!--扫描service层的类-->
<context:component-scan base-package="cn.itsource.aisell.service" />
<!--
db.properties -> dataSource(配置数据源[连接池dbcp]) -> EntityManagerFactory -> dao -> service
-> 事务 -> controller(集成SpringMVC) -> easyui
-->
<!--1.读取db.properties, 注意:不要忘了加classpath-->
<context:property-placeholder location="classpath:jdbc.properties" />
<!--2.配置dbcp连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--
JPA:ORM规范  -> 很多框架实现了这个规范(hibernate,openjpa,toplink,...)
3.配置EntityManagerFactory对象
3.1 基本配置都是写在Spring中(四大金刚,建表策略,方言,是否显示SQL)
3.2 Spring来创建这个对象(准备一个domain,如果运行的时候创建了表,就代表这个对象是成功的)
alt+insert -> JPA -> LocalContainerEntityManagerFactoryBean
ctrl+t/f4 : 有办法看结构
-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--扫描JPA支持的注解-->
<property name="packagesToScan" value="cn.itsource.aisell.domain" />
<!--
告诉Spring我们使用的是哪一个框架来完成JPA规范
这里就需要我们配置一个适配器
jpaVendorAdapter:JPA需要配置的适配器(我们会选择hibernate)
-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--方言-->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<!--
建表策略(已经有表有数据,不要删除了)
-->
<property name="generateDdl" value="false" />
<!--是否显示sql-->
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<!--4.加上事务-->
<!--4.1 准备事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!--4.2 开启(注解)事务支持-->
<tx:annotation-driven transaction-manager="transactionManager" />

</beans>

2.3准备domain

  1. BaseDomain(domain层的父类)

jpa中父类domain必需要加上:

@MappedSuperclass

/**
* 泛化:继承关系
* 在我们JPA,如果要抽取一个父类,就必需加上 @MappedSuperclass
*  非常明确定的告诉JPA,这是一个用于映射的父类
*/
@MappedSuperclass
public class BaseDomain {
@Id
@GeneratedValue
protected Long id;

//getter,setter ...
}

2.Employeee类

@Entity
@Table(name = "employee")
public class Employee extends BaseDomain {

private String username;
private String password;
private Integer age;
private String email;
//getter,setter ...

}

2.4准备Repository接口(相当于Dao层)

/**
* 关于Employee对象的CRUD(分页排序) 就写完了
*  泛型一:对哪一个实体做CRUD
*  泛型二:主键的类型
*/
public interface EmployeeRepository extends JpaRepository<Employee,Long> {
...
}

2.5扫描repository

在applicationContext.xml添加

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
...
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
...
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
">
...

<!-- 让SpringDataJpa去扫描repository -->
<jpa:repositories base-package="cn.helin.aisell.repository"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager" />

</beans>

3.CRUD功能

3.1基本crud

查询所有:

employeeRepository.findAll()

查询一条数据:

employeeRepository.findOne(1L)

添加/修改:

employeeRepository.save(employee)

删除 :

employeeRepository.delete(274L)

3.2测试CRUD

看看自己是否配置正确了的

@Autowired
EmployeeRepository employeeRepository;
/*查询所有*/
@Test
public void testFindAll() throws Exception {
List<Employee> list = employeeRepository.findAll();
list.forEach(e-> System.out.println(e));
}
//查询一个信息
@Test
public void testFindOne() throws Exception {
Employee one = employeeRepository.findOne(1L);
System.out.println(one);
}
//添加一个
@Test
public void testSave() throws Exception {
Employee employee = new Employee();
employee.setAge(123);
employee.setUsername("哈哈");
employeeRepository.save(employee);
}
//修改信息
@Test
public void testUpdate() throws Exception {
Employee employee = new Employee();
employee.setId(274L);
employee.setUsername("驻巴基");
employeeRepository.save(employee);
}
//删除一个
@Test
public void testDelete() throws Exception {
employeeRepository.delete(274L);
}
//分页功能
@Test
public void testPage() throws Exception {
PageRequest pageRequest = new PageRequest(0,10);
Page<Employee> page = employeeRepository.findAll(pageRequest);

page.forEach(e-> System.out.println(e));

}
//排序功能
@Test
public void testSort() throws Exception {
Sort age = new Sort(Sort.Direction.DESC, "age");
List<Employee> all = employeeRepository.findAll(age);
all.forEach(e-> System.out.println(e));

}
//分页排序
@Test
public void testPageandSort() throws Exception {
//创建排序对象
Sort age = new Sort(Sort.Direction.DESC, "age");
//创建分页对象
PageRequest pageRequest = new PageRequest(0, 10,age);
Page<Employee> all = employeeRepository.findAll(pageRequest);
all.forEach(e-> System.out.println(e));
}

3.3根据条件进行查询

在repoitory接口里面写名称规则

//根据用户名查询数据
Employee findByUsername(String username);
//根据用户名模糊查询
List<Employee> findByUsernameLike(String username);
//根据用户名和邮件查询
List<Employee> findByUsernameLikeAndEmailLike(String username,String email);

测试代码

//根据用户名查询
@Test
public void testFindByname() throws Exception {
Employee username = employeeRepository.findByUsername("哈哈");
System.out.println(username);
}
/**
* 根据用户名模糊查询(规范名)
*/
@Test
public void testFindBynameLike() throws Exception {
List<Employee> list = employeeRepository.findByUsernameLike("%1%");
list.forEach(e-> System.out.println(e));
}
/**
* 根据用户名和邮件模糊查询(规范名)
*/
@Test
public void testFindNameAndEmail() throws Exception {
List<Employee> list = employeeRepository.findByUsernameLikeAndEmailLike("%1%", "%1%");
list.forEach(e-> System.out.println(e));
}

3.4Query注解查询

在repoitory接口里面写

//根据用户名查询数据
@Query("select o from Employee o where o.username=?1")
Employee query1(String username);
//根据用户名和邮件查询
@Query("select  o from  Employee o where o.username like ?1 and o.email like ?2 ")
List<Employee> query2(String username,String email);

测试代码

@Test
public void testQuery1() throws Exception {
Employee admain = employeeRepository.query1("admain");
System.out.println(admain);
}
@Test
public void testQuery2() throws Exception {
List<Employee> list = employeeRepository.query2("%1%", "%2%");
list.forEach(e-> System.out.println(e));

3.5原生SQL

//原生SQL的使用
@Query(nativeQuery = true,value = "select * from employee")
List<Employee> query3();

测试代码

@Test
public void testQuery3() throws Exception {
List<Employee> list = employeeRepository.query3();
list.forEach(e-> System.out.println(e));
}

4.JpaSpecificationExecutor

先为你介绍一下,为后面的项目方法做铺垫

  • 是一个JPA的规范执行者
  • JPA2.0提供的Criteria API的使用封装
  • 需要咱们的的repository继承JpaSpecificationExecutor接口
  • public interface EmployeeRepository extends JpaRepository<Employee,Long>,JpaSpecificationExecutor<Employee>

4.1简单的查询

@Test
public void testJpaSpecificationExecutor01() throws Exception{
/**
* 这里的查询我们需要自己去定义规则:Specification
*/
List<Employee> list = employeeRepository.findAll(new Specification<Employee>() {
/**
* 这个方法就是帮咱们创建规则的方法,只要把这个方法搞定,咱们就可以完成查询了
* @param root(根) : 代表了可以查询和操作的实体对象的根
*                可以帮助我们获取到实体对应的字段
* @param query(查询) : 代表一个specific的顶层查询对象
*                 包含查询的各个部分,比如select,from,where,group by ,order by 等
*                  还可以支持and ,or的功能
* @param cb :用来构建CriteriaQuery的构建器对象(相当于条件或者说条件组合)
*                  主要判断关系(和这个字段是相等,大于,小于like等)
*                  支持 and,or的功能
* @return Predicate:表明; 阐明; 断言
*          你把它当成  where username like ? and email like ? and age > ? ...
*/
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//1.拿到Employee中的username字段
Path usernamePath = root.get("username");
//2.加上字段的判断关系
// 参数1:字段(表达式)  2.值
Predicate p1 = cb.like(usernamePath, "%1%");
return p1;
}
});

list.forEach(e-> System.out.println(e));
}

4.2多个条件查询

@Test
public void testJpaSpecificationExecutor02() throws Exception{
//Specification:查询规则
List<Employee> list = employeeRepository.findAll(new Specification<Employee>() {
// root:拿到字段(表达式)  cb:设置条件(>,<,=,like),and/or
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//拿到username并设置条件
Path usernamePath = root.get("username");
Predicate p1 = cb.like(usernamePath, "%1%");
//拿到email并设置条件
Path emailPath = root.get("email");
Predicate p2 = cb.like(emailPath, "%2%");
//拿到age并设置条件 gt/lt:大于/小于   ge/le:大于等于/小等等于
Path agePath = root.get("age");
Predicate p3 = cb.gt(agePath, 18);
//把条件结合起来
return cb.and(p1, p2, p3);
}
});

list.forEach(e-> System.out.println(e));
}

4.3 查询+分页+排序

//查询+分页
@Test
public void testJpaSpecificationExecutor2() throws Exception {
//创建分页对象
PageRequest pageRequest = new PageRequest(0, 10);
Page<Employee> list = employeeRepository.findAll(new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
Path path = root.get("username");
return cb.like(path, "%1%");
}
}, pageRequest);
list.forEach(e-> System.out.println(e));
}
//查询+分页+排序
@Test
public void testJpaSpecificationExecutor3() throws Exception {
//创建排序对象
Sort sort = new Sort(Sort.Direction.DESC, "age");
//创建分页对象
PageRequest pageRequest = new PageRequest(0, 10, sort);
Page<Employee> list = employeeRepository.findAll(new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
Path username = root.get("username");

return cb.like(username, "%1%");
}
},pageRequest);
list.forEach(e-> System.out.println(e));
}

5.jpa-spec

5.1简单查询

//根据用户名,email.年龄大于20岁进行模糊查询
@Test
public void testJpaSpec1() throws Exception {
Specification<Employee> spe = com.github.wenhao.jpa.Specifications.<Employee>and()
.like("username","%1%")
.like("email","%2%")
.gt("age", 20)
.build();
List<Employee> list = employeeRepository.findAll(spe);
list.forEach(e-> System.out.println(e));
}
//分页+排序+条件查询
@Test
public void testJpaSpec2() throws Exception {
//创建排序对象
Sort sort = new Sort(Sort.Direction.DESC, "age");
//创建分页对象
PageRequest pageRequest = new PageRequest(0, 10, sort);
Specification<Employee> spe = Specifications.<Employee>and()
.like("username","%1%")
.build();
Page<Employee> all = employeeRepository.findAll(spe, pageRequest);
all.forEach(e-> System.out.println(e));

}

6.抽取Query

Query是咱们的查询对象

6.1 BaseQuery

原因:

  • 有经验的人都会创建父类 方便扩展
  • 公共的代码
  • 制定规范
  • 目前咱们Query需要做的
      四个字段(currrentPage,pageSize,orderType,orderName)
    • 让每个子类都有一个:
      createSpec()
    • 创建一个order对象
    • 解决了传过来的是当前页从1开始(SpringDataJpa是从0开始计算)
    public abstract class BaseQuery {
    
    //分页 -> 当前第几页
    private int currentPage=1;
    //分页 -> 每页条数
    private int pageSize=10;
    //排序 -> 排序的类型 true(DESC)/false(ASC)
    private boolean orderType;
    //排序 -> 排序的字段 -> 如果这个字段为null,就代表不排序
    private String orderName;
    
    //创建排序对象
    public Sort createSort(){
    if(StringUtils.isNotBlank(orderName)){
    //orderName有值才做排序
    Sort sort = new Sort(orderType?Sort.Direction.DESC:Sort.Direction.ASC,orderName);
    return sort;
    }
    return null;
    }
    //要求只要继承了我,就必需有一个方法叫:createSpec()
    public abstract Specification createSpec();
    
    public int getJpaPage() {
    return currentPage-1;
    }
    
    //getter,setter....
    
    }

    6.2EmployeeQuery

    • 设置当前对应的Domain的特有查询字段
    • 实现
      createSpec()
    /**
    * 员工查询
    */
    public class EmployeeQuery extends BaseQuery {
    
    //用户名
    private String username;
    //邮件
    private String email;
    //年龄
    private Integer age;
    
    //查询的规则应该在查询对象中来创建
    @Override
    public Specification createSpec(){
    Specification<Employee> specification = Specifications.<Employee>and()
    .like(StringUtils.isNotBlank(username), "username", "%" + username + "%")
    .like(StringUtils.isNotBlank(email), "email", "%" + email + "%")
    .gt(age != null, "age", age)
    .build();
    return specification;
    }
    
    //getter,setter...
    }

    6.3测试

    /**
    * 有Query的查询
    * @throws Exception
    */
    @Test
    public void testJpaSpec04() throws Exception{
    //以后咱们的查询数据是从前台传过来的,就会生成EmployeeQuery对象
    EmployeeQuery query = new EmployeeQuery();
    //        query.setUsername("1");
    //        query.setEmail("2");
    //        query.setAge(18);
    query.setOrderName("age");
    query.setOrderType(true);
    
    //创建排序对象
    Sort sort = query.createSort();
    //创建分页对象(分页对象从前台传过来)
    Pageable pageable = new PageRequest(query.getJpaPage(),query.getPageSize(),sort);
    //规则对象(查询条件)
    Specification<Employee> spec = query.createSpec();
    //功能执行
    Page<Employee> page = employeeRepository.findAll(spec, pageable);
    page.forEach(e-> System.out.println(e));
    }

    #####项目第二天

    1 repository层(dao层)

    1.1 创建BaseRepository

    /**
    * 公共的父Repository
    * @param <T>
    * @param <ID>
    */
    @NoRepositoryBean//告诉Spring不用创建实现
    public interface BaseRepository<T,ID extends Serializable>  extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {
    }

    1.2 EmployeeRepository

    //注意:必需改成继承BaseRepsitory
    public interface EmployeeRepository extends BaseRepository<Employee,Long>{
    ...
    }

    2 Service层

    2.1 IBaseService:父接口

    /**
    * Service的父接口(所有service都有CRUD)
    */
    public interface IBaseService<T, ID extends Serializable> {
    //添加或者修改
    void save(T t);
    //删除
    /**
    * 联合主键
    * 在JPA中,要求主键必需实现Serializable接口
    * @param id
    */
    void delete(ID id);
    //根据id查询一条数据
    T findOne(ID id);
    //查询所有数据
    List<T> findAll();
    
    //1.根据查询条件(query对象)查询对应的数据
    List<T> queryAll(BaseQuery query);
    
    //2.根据查询条件(query对象)查询对应的分页(排序)数据
    Page<T> queryPage(BaseQuery query);
    
    //3.根据JPQL进行查询
    /**
    *
    * @param jpql select o.username,o.age from ... where username like ? and email like ?
    * @param params
    * @return
    */
    List findByJpql(String jpql,Object... params);
    }

    2.2 BaseServiceImpl:父实现

    /**
    * 抽象的类是无法创建对象的(只能做父类)
    * 实现类无法确定接口中泛型的类型
    * @param <T>
    * @param <ID>
    */
    @Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
    public abstract class BaseServiceImpl<T,ID extends Serializable> implements IBaseService<T,ID> {
    /**
    *  Spring会把相应的BaseRepository<T,ID>实现对象注入进来
    *      BaseRepository -> EmployeeRepository<Employee,Long>
    *                        DepartmentRepository<Department,Long>
    *                        RoleRepository<Role,Long>
    *      我们怎么确定注入的是哪一个对象呢? -> 当用的时候自然就知道了!!
    *          EmployeeServiceImpl extends BaseServiceImpl<Employee,Long>
    *              new EmployeeServiceImpl().save();
    */
    @Autowired
    private BaseRepository<T,ID> baseRepository;
    //自动从当前上下文中获取这个对象
    @PersistenceContext
    private EntityManager entityManager;
    
    @Override
    @Transactional
    public void save(T t) {
    baseRepository.save(t);
    }
    @Override
    @Transactional
    public void delete(ID id) {
    baseRepository.delete(id);
    }
    @Override
    public T findOne(ID id) {
    return baseRepository.findOne(id);
    }
    @Override
    public List<T> findAll() {
    return baseRepository.findAll();
    }
    //根据查询条件(query对象)查询对应的数据
    @Override
    public List<T> queryAll(BaseQuery query) {
    //1.拿到规则
    Specification spec = query.createSpec();
    //2.根据规则进行查询
    return baseRepository.findAll(spec);
    }
    //根据查询条件(query对象)查询对应的分页数据
    @Override
    public Page<T> queryPage(BaseQuery query) {
    //1.拿到规则
    Specification spec = query.createSpec();
    //2.拿到排序对象
    Sort sort = query.createSort();
    //3.拿到分页对象
    Pageable pageable = new PageRequest(query.getJpaPage(),query.getPageSize(),sort);
    //4.返回分页对象
    return baseRepository.findAll(spec,pageable);
    }
    //执行jpql,就必需要EntityManager对象
    /**
    * @param jpql select o.username,o.age from ... where username like ? and email like ?
    * @param params 对应的是?的值 -> 可变参数就是数组
    * @return
    */
    @Override
    public List findByJpql(String jpql, Object... params) {
    //1.获取query对象
    Query query = entityManager.createQuery(jpql);
    //2.循环params参数(对应的是?的值)
    for (int i = 0; i < params.length; i++) {
    //这里设置值是从1开始的
    query.setParameter(i+1,params[i]);
    }
    //3.返回数据
    return query.getResultList();
    }
    }

    2.3 IEmployeeService

    /**
    * 现在没有代码,不代表以后没有!以后会有一些关于员工的特有的功能
    */
    public interface IEmployeeService extends IBaseService<Employee,Long> {
    }

    2.4 EmployeeServiceImpl

    @Service
    public class EmployeeServiceImpl extends BaseServiceImpl<Employee,Long>
    implements IEmployeeService {
    }

    2.5 测试

    创建SringTest类 抽取test:

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

    测试类:EmployeeServiceImplTest 继承SpringTest

    public class EmployeeServiceImplTest extends SpringTest {
    @Autowired
    private IEmployeeService employeeService;
    @Test
    //查询所有
    public void testFindAll() throws Exception {
    employeeService.findAll().forEach(e-> System.out.println(e));
    }
    @Test
    //根据名字进行模糊查询
    public void testQueryAll() throws Exception {
    EmployeeQuery query = new EmployeeQuery();
    query.setUsername("1");
    // Page<Employee> employees = employeeService.pageAll(query);
    List<Employee> queryAll = employeeService.queryAll(query);
    queryAll.forEach(e-> System.out.println(e));
    }
    }

    3 SpringMVC的集成

    3.1 准备applicationContext-mvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    ">
    
    <!--1.扫描相应的controller层-->
    <context:component-scan base-package="cn.helin.aisell.controller" />
    <!--2.静态资源放行-->
    <mvc:default-servlet-handler />
    <!--3.mvc的注解支持-->
    <mvc:annotation-driven />
    <!--4.视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" /><!--前缀-->
    <property name="suffix" value=".jsp" />
    </bean>
    <!--5.上传解析器 CommonsMultipartResolver-->
    <!-- 注意:上传解析器的id必需:multipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize">
    <value>10485760</value>
    </property>
    </bean>
    
    </beans>

    3.2准备web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1">
    
    <!--SpringMVC的配置和Spring的配置要单独读取,否则后面集成其它框架会出问题-->
    
    <!--运行与读取spring的配置-->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    
    <!--配置mvc的核心控制器-->
    <servlet>
    <servlet-name>dispatchServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--读取mvc配置-->
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext-mvc.xml</param-value>
    </init-param>
    <!--tomcat启动用创建-->
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>dispatchServlet</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    <!--编码过滤-->
    <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    </web-app>

    3 .3 UIPage类

    • 由于我们前面要集成Easyui
    • Easyui在分页时想要的数据结构
      {total:xx,rows:[...]}
    • 准备
      UIPage
      来匹配这个结构
    public class UIPage<T> {
    private Long total; //总条数
    private List<T> rows; //每页数据
    
    public UIPage(Page page) {
    total = page.getTotalElements();
    rows = page.getContent();
    }
    
    public Long getTotal() {
    return total;
    }
    
    public void setTotal(Long total) {
    this.total = total;
    }
    
    public List<T> getRows() {
    return rows;
    }
    
    public void setRows(List<T> rows) {
    this.rows = rows;
    }
    }

    3.4 准备Controller

    public class EmployeeController {
    @Autowired
    private IEmployeeService employeeService;
    @RequestMapping("/index")
    public String index(){
    return "employee/index";
    }
    @RequestMapping("/list")
    @ResponseBody
    public List<Employee> findAll(){
    List<Employee> list = employeeService.findAll();
    return list;
    }
    }

    4.EasyUI的集成

    4.1 准备head.jsp

    用来抽取重复的代码,比如引入头文件

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%--easyui的样式--%>
    <link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
    <%--easyui的图标 --%>
    <link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">
    <%--jQuery的支持--%>
    <script type="text/javascript" src="/easyui/jquery.min.js"></script>
    <%--jQuery的扩展包 --%>
    <script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script><%--easyui的核心功能--%>
    <script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
    <%--国际化--%>
    <script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>

    4.2 employee的jsp代码

    <%--
    Created by IntelliJ IDEA.
    User: Administrator
    Date: 2019/12/10
    Time: 11:38
    To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>Title</title>
    <%--引入头部文件--%>
    <%@include file="/WEB-INF/views/head.jsp"%>
    <script src="/js/model/employee.js"></script>
    </head>
    <body>
    <div id="toolbar" style="padding:5px;height:auto">
    <div style="margin-bottom:5px">
    <a href="#" data-method="add" class="easyui-linkbutton" iconCls="icon-add" plain="true">添加</a>
    <a href="#" data-method="update" class="easyui-linkbutton" iconCls="icon-edit" plain="true">修改</a>
    <a href="#" data-method="delete" class="easyui-linkbutton" iconCls="icon-remove" plain="true">删除</a>
    </div>
    <form id="searchForm" method="post">
    用户名: <input name="username" class="easyui-textbox" style="width:80px">
    邮箱: <input name="email" class="easyui-textbox" style="width:80px">
    <a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查询</a>
    </form>
    </div>
    <table id="datagrid"  class="easyui-datagrid"
    data-options="url:'/employee/page',fitColumns:true,singleSelect:true,fit:true,pagination:true,toolbar:'#toolbar'">
    <thead>
    <tr>
    <th data-options="field:'id',width:100">编码</th>
    <th data-options="field:'username',width:100">名称</th>
    <th data-options="field:'age',width:100">年龄</th>
    <th data-options="field:'password',width:100">密码</th>
    <th data-options="field:'email',width:100">邮件</th>
    </tr>
    </thead>
    </table>
    </body>
    </html>

    4.3 employee.js

    $(function () {
    //常用的元素都先在这里获取到
    var datagrid = $("#datagrid");
    var searchForm = $("#searchForm")
    //响应事件
    $("*[data-method]").on("click",function () {
    //拿到对应的方法
    var methodName = $(this).data("method");
    //调用方法
    itsource[methodName]();
    })
    itsource={
    add(){
    alert("asdiaiab")
    },
    update(){},
    delete(){
    },
    //高级查询
    search(){
    }
    };
    })

    5.准备分页查询

    UIPage类就是为了解决EasyUI响应的数据类型是:{total:xx,rows:[…]}

    5.1在controller层添加分页查询功能

    //分页查询
    @RequestMapping("/page")
    @ResponseBody
    public UIPage list(EmployeeQuery query){
    /*System.out.println(employeeService.pageAll(query).getTotalElements());
    System.out.println(employeeService.pageAll(query).getTotalPages());*/
    return new UIPage(employeeService.pageAll(query));
    }

    5.2 高级查询

    在head.jsp引入jquery扩展包

    <%--jQuery的扩展包 --%>
    <script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>

    在employee.js中写高级查询方法

    //高级查询
    search(){
    //1.拿到查询的值
    var params = searchForm.serializeObject();
    //2.进行查询
    datagrid.datagrid("load",params);
    }

    6 删除功能

    6.1 准备一个JsonResult类型

    原因是easyUI接受的数据是json对象

    /**
    * 删除返回的信息
    */
    public class JsonResult {
    //代表是否成功
    private boolean success = true;
    //代表相应的信息(一般是错误信息)
    private String msg;
    
    public JsonResult(){}
    public JsonResult(boolean success, String msg) {
    this.success = success;
    this.msg = msg;
    }
    //geter//seter
    }

    6.2 EmployeeController提供删除功能

    /**
    * 前台会传一个id过来
    *  需要返回:{success:true/false,msg:"xx"}
    *     返回这种结构有两种方法:1种是写map, 1种是直接返回对象
    */
    @RequestMapping("/delete")
    @ResponseBody
    public JsonResult delete(Long id){
    try {
    employeeService.delete(id);
    return new JsonResult();
    } catch (Exception e) {
    e.printStackTrace();
    //失败后返回的结果
    return new JsonResult(false,e.getMessage());
    }
    }

    6.3 employee.js`完成删除

    delete(){
    //获取选择的行
    var row = datagrid.datagrid("getSelected");
    if(!row){
    $.messager.alert('警告','请选择要删除的行',"warning");
    return;
    }
    $.messager.confirm('确认','您确认想要删除记录吗?',function(r){
    if (r){
    //4.通过Ajax请求进行删除
    // 参数一:请求路径   参数二:请求参数   参数三:回调
    // result:是后端返回的结果
    $.get("/employee/delete",{id:row.id},function (result) {
    if(result.success){
    //5.刷新页面
    datagrid.datagrid("reload");
    }else{
    //给出错误提示
    $.messager.alert('提示',`删除失败,原因是:${result.msg}`,"error");
    }
    })
    }
    });
    },

    7 懒加载问题

    在domain层的employee类上,在多对一关系后面添加懒加载代码

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;

    问题一:noSession

    是因为entityManager提前结束了关系

    解决办法:

    web.xml中配置Spring的过滤器

    <!--解决no-session的问题-->
    <filter>
    <filter-name>openEntityManager</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>openEntityManager</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    问题二:noSerializer

    因为hibernate添加了一些字段(变成Json时报错)

    解决方法1:

    字段上面加注解

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})//加这个注解
    private Department department;

    解决方法2:

    配置一个类:CustomMapper

    public class CustomMapper extends ObjectMapper {
    public CustomMapper() {
    this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    // 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false
    this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }
    }

    配置xml:applicationContext-mvc.xml

    <!-- Spring MVC 配置 -->
    <mvc:annotation-driven>
    <mvc:message-converters>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="supportedMediaTypes">
    <list>
    <value>application/json; charset=UTF-8</value>
    <value>application/x-www-form-urlencoded; charset=UTF-8</value>
    </list>
    </property>
    <!-- No serializer:配置 objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 -->
    <property name="objectMapper">
    <bean class="cn.itsource.aisell.common.CustomMapper"></bean>
    </property>
    </bean>
    </mvc:message-converters>
    </mvc:annotation-driven>

    项目的第一阶段就先这样完成了,很简单的CRUD

    • 点赞
    • 收藏
    • 分享
    • 文章举报
    猫巷的故事 发布了4 篇原创文章 · 获赞 0 · 访问量 28 私信 关注
  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: