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
- 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
- 把JpaSpecificationExecutor变得更加简单的
- 使用的时候需要导包(咱们已经导入)
- 文档: https://github.com/wenhao/jpa-spec/blob/master/docs/3.1.0_cn.md
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
原因:
- 有经验的人都会创建父类 方便扩展
- 公共的代码
- 制定规范
-
四个字段(currrentPage,pageSize,orderType,orderName)
createSpec()
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
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- AiSell智能销售系统2——权限与菜单
- AiSell智能销售系统2
- 智能销售系统准备
- 智能销售系统day6
- 基于SSJ智能销售系统的模版开发-01
- 智能销售系统day7
- 基于SSJ智能销售系统的模版开发-02
- 智能销售系统登录和授权
- 基于SSJ智能销售系统的模版开发-03
- 智能销售系统技术心得——第二篇
- 智能销售系统的订单采购和报表
- 智能销售系统技术心得——第三篇
- 智能销售系统-基础crud
- 智能销售系统-模板技术
- 基于SSJ智能销售系统的模版开发-04
- 智能销售系统day8
- 智能销售系统-登录&角色
- 基于SSJ智能销售系统的模版开发-06
- 智能销售系统CRUD
- 基于SSJ智能销售系统的模版开发-07