写这次笔记,首先是最近工作需要,单位很多系统都是基于springboot开发的,其次是之前对于目前主流的web开发技术也前后也多少都了解了一些,只是觉得现在实现一个同样的功能,可以采用的开发框架太多了,其次就算采用同一个框架,他的使用方式也非常多,比如mybatis这样的主流数据库框架,在具体使用上也有采用注解的,或者配置文件的,或者直接写sql的等等,让我有点混淆,没有找到一种标准化,相对易用的方式。因此,这次笔记主要是针对springboot和mybatis逆向工程+注解的形式搭建的一个简单的增删改查的web程序的记录,包括其中一些关键点。下面就是具体的实现步骤:
1、项目名:springboot_mybatis
开发工具:eclipse JavaEE版本,JDK1.8,maven配置如下:
2、构建一个maven工程,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>curry</groupId>
<artifactId>chen</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>chen</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<dependencies>
<!-- Springboot核心jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- web开发包:包含Tomcat和Springmvc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Junit测试jar包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring-boot热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- 配置thymeleaf 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- jdbc链接容器 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--逆向工程依赖的坐标-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--逆向工程插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>
</project>
因为要逆向工程,因此配置了 org.mybatis.generator插件
3、数据库建好一张简单的表,然后进行逆向工程,生成bean、example、mapper、以及mapper.xml映射:
(1)在resources下建一个generatorConfig.xml文件:主要配置数据库连接信息,生成的bean、mapper.xml、mapper接口存放位置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
<context id="store" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
<!-- 是否去除所有自动生成的文件的时间戳,默认为false -->
<property name="suppressDate" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/springboot" userId="root"
password="123456">
</jdbcConnection>
<!-- targetPackage:包名称(自定义) targetProject:项目路径(自定义) -->
<!--定义生成的实体类放置的位置 -->
<javaModelGenerator
targetPackage="chen.bean" targetProject="src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 配置生成的映射配置文件XxxMapper.xml放置的位置 -->
<!-- targetPackage:包名称(自定义) targetProject:项目路径(自定义) -->
<sqlMapGenerator targetPackage="chen.dao.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- 配置生成相应XxxMapper接口放置的位置 -->
<!-- targetPackage:包名称(自定义) targetProject:项目路径(自定义) -->
<javaClientGenerator
targetPackage="chen.dao.mapper"
targetProject="src/main/java" type="XMLMAPPER">
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 对应的数据库表名 -->
<table tableName="player" />
</context>
</generatorConfiguration>
(2)执行逆向工程,这边采用的是写一个main方法,去加载generatorConfig.xml的方式。代码如下:(同事介绍一种可以直接运行generatorConfig.xml的方式,但是我没有成功)
package test;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class GeneratorSqlmap {
public void generator() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指向逆向工程配置文件
File configFile = new File("./resources/generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(3)执行上述代码后,生成目录如下:(多次逆执行向工程,可能会生成重复的内容,可以清理后再生成)
红框部分为自动生成的东西。主要介绍下生成东西的作用:
Player就是数据库表player的bean类,这个很好理解。
PlayerExample就厉害了,他是针对Player表每个字段,自动生成增删改查的条件设定的方法。在下文具体执行数据库操作的时候,就会用到。
PlayerMapper是具体的数据库操作方法,而PlayerMapper.xml就是对PlayerMapper具体操作方法的实现映射。也就是PlayerMapper中每一个方法,都有在PlayerMapper.xml中的具体的sql实现。
到此,逆向工程结束
至此操作后,该工程已经具备了DAO层(数据操作层:库表和实体映射以及对表的操作),作为一个springboot项目,目前还差Control层和Service层。
Control层:对前端或外部请求进行分发给具体的Service
Service层:完成具体的业务处理,包括执行一些逻辑处理,通过调用DAO层的方法等实现
4、Service层:
(1)首先要编写一个mybatis-config.xml文件,配置数据库环境,数据库操作时映射类的包路径等。主要实际运用中,可以会用到多套环境,这里可以设置各环境的数据库信息。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="application.properties" />
<!-- <properties resource="application.yml" /> -->
<settings>
<setting name="cacheEnabled" value="false" />
<setting name="useGeneratedKeys" value="true" />
<setting name="defaultExecutorType" value="REUSE" />
</settings>
<environments default="development">
<environment id="development">
<!--配置管理实务的 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源的取值 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
<!-- <dataSource type="POOLED">
<property name="driver" value="${spring.datasource.driver-class-name}" />
<property name="url" value="${spring.datasource.url}" />
<property name="username" value="${spring.datasource.username}" />
<property name="password" value="${spring.datasource.password}" />
</dataSource> -->
</environment>
</environments>
<mappers>
<package name="chen.dao.mapper" />
</mappers>
</configuration>
上述读取数据库配置信息时,<properties resource="application.properties" />指定了属性文件,数据库配置数据从该文件中读取。也尝试用application.yml中读取,但是没有成功。
resources下建application.properties文件:
#jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springboot
jdbc.username=root
jdbc.password=123456
(2)编写Service操作类:
包括获取数据库操作的session对象 以及一系列的增删改查操作。
该类必须加上Service注解,不然后续无法注入。在具体进行数据库操作的时候,主要运用了example构造条件,具体细节可以看代码中的注释。
package chen.service;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import chen.bean.Player;
import chen.bean.PlayerExample;
import chen.dao.mapper.PlayerMapper;
@Service //这个注解必须加,不然PlayerController中注入无法被扫描到
public class PlayerService {
private SqlSession sqlSession;
public PlayerService() throws IOException {
// 读取mybatis核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 创建工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
// 创建SQLSession对象
sqlSession = sqlSessionFactory.openSession();
}
public void insert(Player player) throws IOException {
/* Player pl = new Player();
pl.setAge(20);
pl.setHight("191cm");
pl.setName("curry");*/
PlayerMapper mapper = sqlSession.getMapper(PlayerMapper.class);
System.out.println(mapper.insert(player));
sqlSession.commit();
}
public List<Player> selectPlayer() throws IOException {
PlayerMapper mapper = sqlSession.getMapper(PlayerMapper.class);
List<Player> lp = new ArrayList<Player>();
PlayerExample pe = new PlayerExample();
PlayerExample.Criteria criteria = pe.createCriteria();
criteria.andAgeEqualTo(20);
lp = mapper.selectByExample(pe);
for(Player player:lp) {
System.out.println("身高为:" + player.getHight());
}
return lp;
}
public void updatePlayer() throws IOException {
PlayerMapper mapper = sqlSession.getMapper(PlayerMapper.class);
PlayerExample pe = new PlayerExample();
PlayerExample.Criteria criteria = pe.createCriteria();
Player player = new Player();
player.setId(5);
player.setName("jordan");
player.setNumber(23);
mapper.updateByPrimaryKeySelective(player); //Selective只对指定的字段进行修改
//mapper.updateByPrimaryKey(player);//对所有字段按照新传入的player进行覆盖
sqlSession.commit();
}
public void deletePlayer() throws IOException {
PlayerMapper mapper = sqlSession.getMapper(PlayerMapper.class);
PlayerExample pe = new PlayerExample();
PlayerExample.Criteria criteria = pe.createCriteria();
criteria.andNameLike("jor%");
mapper.deleteByExample(pe);
sqlSession.commit();
}
public void destroy(){
sqlSession.close();
}
}
5、Controller层:
对Service类PlayerService进行了注入。
package chen.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import chen.service.PlayerService;
import chen.bean.Player;
@Controller
public class PlayerController{
@Autowired
private PlayerService ps;
@RequestMapping("/hello")
public String hello() {
return "index2";
}
@RequestMapping("/insert_player")
@ResponseBody //如果添加该注解,则直接返回return的值,比如不需要跳转页面,只是做接口返回时
public String insertPlayer(Player player) {
try {
ps.insert(player);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "insert_success";
}
@RequestMapping("/select_player")
public String selectPlayer(Model model) {
List<Player> lp = new ArrayList<Player>();
try {
lp = ps.selectPlayer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
model.addAttribute("playerList", lp);
return "list"; //不打@ResponseBody标签,直接返回到对应名称的页面
}
}
主要实现从页面表单插入数据以及从数据库中选择所有球员信息列表。其他Service类中的操作没有用到