目錄
1 目錄結構
2 全局配置文件
2.1 application.properties(resources下,自動生成)
2.2 mybatis-config.xml(resources下,手動創建)
2.3 config文件夾(java包下,手動創建)
2.3.1 mapper文件夾
2.3.2 service文件夾
3 代碼流程
3.1 第一步:Entity層
3.2 第二步:Dao層
3.3 第三步:Mapper配置文件
3.4 第四部:測試Dao層類
3.4 第五步:service層
3.5 第六步:controller層
4 運行效果
1 目錄結構
注意:
1)Java包下的子文件夾需要手動創建
2)resources下的mapper文件夾和mybatis-config.xml文件需要手動創建。
2 全局配置文件
全局配置文件主要包括數據庫配置、服務端口配置、事務配置等。
2.1 application.properties(resources下,自動生成)
application.properties是全局配置文件,通過修改此文件可以實現自定義配置,如端口、根路徑等。
本模板僅配置數據源配置,配置如下:
#DataSource #數據庫驅動(高版本mysql配置) jdbc.driver=com.mysql.cj.jdbc.Driver #數據庫鏈接(高版本mysql配置) jdbc.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT #數據庫用戶名 jdbc.username=root #數據庫密碼 jdbc.password=1234 #Mybatis mybatis_config_file=mybatis-config.xml mapper_path=/mapper/**.xml # 要與包名一致 type_alias_package=com.example.demo.entity
2.2 mybatis-config.xml(resources下,手動創建)
此文件需要手動創建。名稱可以自定義,需要與application.properties中一致。
配置如下:
<?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> <!-- 配置全局屬性 --> <settings> <!-- 使用jdbc的getGeneratedKeys獲取數據庫自增主鍵值 --> <setting name="useGeneratedKeys" value="true" /> <!-- 使用列標簽替換列別名 默認:true --> <setting name="useColumnLabel" value="true" /> <!-- 開啟駝峰命名轉換:Table{create_time} -> Entity{createTime} --> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings> </configuration>
2.3 config文件夾(java包下,手動創建)
本項目中,config文件夾下包含兩個子文件夾mapper和service
2.3.1 mapper文件夾
mapper文件夾中為數據源的相關配置,主要實現全局配置文件Application.properties中的配置生效。
1)DataSourceConfiguration(數據配置類)
代碼如下:

package com.example.demo.config.mapper;
import java.beans.PropertyVetoException;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* 配置datasource到ioc容器里面
*
* @author xiangze
*
*/
@Configuration
// 配置mybatis mapper的掃描路徑
@MapperScan("com.example.demo.dao")
public class DataSourceConfiguration {
@Value("${jdbc.driver}")
private String jdbcDriver;
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
/**
* 生成與spring-dao.xml對應的bean dataSource
*
* @return
* @throws PropertyVetoException
*/
@Bean(name = "dataSource")
public ComboPooledDataSource createDataSource() throws PropertyVetoException {
// 生成datasource實例
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 跟配置文件一樣設置以下信息
// 驅動
dataSource.setDriverClass(jdbcDriver);
// 數據庫連接URL
dataSource.setJdbcUrl(jdbcUrl);
// 設置用戶名
dataSource.setUser(jdbcUsername);
// 設置用戶密碼
dataSource.setPassword(jdbcPassword);
// 配置c3p0連接池的私有屬性
// 連接池最大線程數
dataSource.setMaxPoolSize(30);
// 連接池最小線程數
dataSource.setMinPoolSize(10);
// 關閉連接后不自動commit
dataSource.setAutoCommitOnClose(false);
// 連接超時時間
dataSource.setCheckoutTimeout(10000);
// 連接失敗重試次數
dataSource.setAcquireRetryAttempts(2);
return dataSource;
}
}
2)SessionFactoryConfiguration(數據庫連接池配置類)
代碼如下:

package com.example.demo.config.mapper; import java.io.IOException; import javax.sql.DataSource; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @Configuration public class SessionFactoryConfiguration { // mybatis-config.xml配置文件的路徑 private static String mybatisConfigFile; @Value("${mybatis_config_file}") public void setMybatisConfigFile(String mybatisConfigFile) { SessionFactoryConfiguration.mybatisConfigFile = mybatisConfigFile; } // mybatis mapper文件所在路徑 private static String mapperPath; @Value("${mapper_path}") public void setMapperPath(String mapperPath) { SessionFactoryConfiguration.mapperPath = mapperPath; } // 實體類所在的package @Value("${type_alias_package}") private String typeAliasPackage; @Autowired private DataSource dataSource; /** * 創建sqlSessionFactoryBean 實例 並且設置configtion 設置mapper 映射路徑 設置datasource數據源 * * @return * @throws IOException */ @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); // 設置mybatis configuration 掃描路徑 sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFile)); // 添加mapper 掃描路徑 PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver(); String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath; sqlSessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources(packageSearchPath)); // 設置dataSource sqlSessionFactoryBean.setDataSource(dataSource); // 設置typeAlias 包掃描路徑 sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasPackage); return sqlSessionFactoryBean; } }
2.3.2 service文件夾
1)TransactionManagementConfiguration(事務配置類)
代碼如下:

package com.example.demo.config.service; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.TransactionManagementConfigurer; /** * 對標spring-service里面的transactionManager * 繼承TransactionManagementConfigurer是因為開啟annotation-driven * * @author xiangze * */ @Configuration // 首先使用注解 @EnableTransactionManagement 開啟事務支持后 // 在Service方法上添加注解 @Transactional 便可 @EnableTransactionManagement public class TransactionManagementConfiguration implements TransactionManagementConfigurer { @Autowired // 注入DataSourceConfiguration里邊的dataSource,通過createDataSource()獲取 private DataSource dataSource; @Override /** * 關於事務管理,需要返回PlatformTransactionManager的實現 */ public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } }
3 代碼流程
編寫代碼的順序,便於快速實現和測試。
3.1 第一步:Entity層
實體類層,需要提前建立數據庫、數據表並添加實例數據。
代碼如下:

package com.example.demo.entity; import java.util.Date; /** * 區域信息 * @author xiangze * */ public class Area { // 主鍵ID private Integer areaId; // 名稱 private String areaName; // 權重,越大越排前顯示 private Integer priority; // 創建時間 private Date createTime; // 更新時間 private Date lastEditTime; public Integer getAreaId() { return areaId; } public void setAreaId(Integer areaId) { this.areaId = areaId; } public String getAreaName() { return areaName; } public void setAreaName(String areaName) { this.areaName = areaName; } public Integer getPriority() { return priority; } public void setPriority(Integer priority) { this.priority = priority; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getLastEditTime() { return lastEditTime; } public void setLastEditTime(Date lastEditTime) { this.lastEditTime = lastEditTime; } }
3.2 第二步:Dao層
編寫接口,代碼如下:

package com.example.demo.dao; import java.util.List; import com.example.demo.entity.Area; public interface AreaDao { /** * 列出區域列表 * * @return areaList */ List<Area> queryArea(); /** * 根據Id列出具體區域 * * @return area */ Area queryAreaById(int areaId); /** * 插入區域信息 * * @param area * @return */ int insertArea(Area area); /** * 更新區域信息 * * @param area * @return */ int updateArea(Area area); /** * 刪除區域信息 * * @param areaId * @return */ int deleteArea(int areaId); }
3.3 第三步:Mapper配置文件
編寫Dao層中的SQL語句,代碼如下:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.dao.AreaDao"> <select id="queryArea" resultType="com.example.demo.entity.Area"> SELECT area_id, area_name, priority, create_time, last_edit_time FROM tb_area ORDER BY priority DESC </select> <select id="queryAreaById" resultType="com.example.demo.entity.Area"> SELECT area_id, area_name, priority, create_time, last_edit_time FROM tb_area WHERE area_id=#{areaId} </select> <insert id="insertArea" useGeneratedKeys="true" keyProperty="areaId" keyColumn="area_id" parameterType="com.example.demo.entity.Area"> INSERT INTO tb_area(area_name,priority, create_time,last_edit_time) VALUES (#{areaName},#{priority}, #{createTime},#{lastEditTime}) </insert> <update id="updateArea" parameterType="com.example.demo.entity.Area"> update tb_area <set> <if test="areaName != null">area_name=#{areaName},</if> <if test="priority != null">priority=#{priority},</if> <if test="lastEditTime != null">last_edit_time=#{lastEditTime}</if> </set> where area_id=#{areaId} </update> <delete id="deleteArea"> DELETE FROM tb_area WHERE area_id = #{areaId} </delete> </mapper>
3.4 第四部:測試Dao層類
測試Dao類是否可以正常操作數據庫。代碼如下:
idea下快捷方式:選中Dao類名,按Alt+Insert(先按Alt再按Insert),勾選要測試的類。具體測試方法需要手動編寫。

package com.example.demo.dao; import static org.junit.Assert.assertEquals; import java.util.Date; import java.util.List; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.example.demo.entity.Area; @RunWith(SpringRunner.class) @SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING) // 按方法名大小升序執行 public class AreaDaoTest { //通過spring容器注入Dao的實現類 @Autowired private AreaDao areaDao; @Test public void testAQueryArea() { List<Area> areaList = areaDao.queryArea(); // 驗證預期值和實際值是否相符 assertEquals(2, areaList.size()); } @Test public void testBInsertArea() { //創建一個區域對象 Area area = new Area(); area.setAreaName("測試區域"); area.setCreateTime(new Date()); area.setPriority(1); //將該對象實例添加入庫 int effectedNum = areaDao.insertArea(area); //檢測影響行數 assertEquals(1, effectedNum); //校驗總數是否+1 List<Area> areaList = areaDao.queryArea(); assertEquals(3, areaList.size()); } @Test public void testCQueryAreaById() { Area area = areaDao.queryAreaById(2); assertEquals("東苑", area.getAreaName()); } @Test public void testDUpateArea() { List<Area> areaList = areaDao.queryArea(); for (Area area : areaList) { if ("測試區域".equals(area.getAreaName())) { // 對比之前的priority值 assertEquals(1, area.getPriority().intValue()); area.setPriority(2); int effectedNum = areaDao.updateArea(area); assertEquals(1, effectedNum); } } } @Test public void testEDeleteArea() { List<Area> areaList = areaDao.queryArea(); for (Area area : areaList) { if ("測試區域".equals(area.getAreaName())) { int effectedNum = areaDao.deleteArea(area.getAreaId()); assertEquals(1, effectedNum); } } // 重新獲取一次列表,看看總數是否少1 areaList = areaDao.queryArea(); assertEquals(2, areaList.size()); } }
3.5 第四步:service層
調用Dao層中的類實現業務邏輯,先寫接口再實現,目錄結構如下:
代碼如下:
1)接口代碼

package com.example.demo.service; import java.util.List; import com.example.demo.entity.Area; public interface AreaService { /** * 獲取區域列表 * * @return */ List<Area> getAreaList(); /** * 通過區域Id獲取區域信息 * * @param areaId * @return */ Area getAreaById(int areaId); /** * 增加區域信息 * * @param area * @return */ boolean addArea(Area area); /** * 修改區域信息 * * @param area * @return */ boolean modifyArea(Area area); /** * 刪除區域信息 * * @return */ boolean deleteArea(int areaId); }
2)實現類代碼

package com.example.demo.service.Impl; import java.io.IOException; import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.example.demo.dao.AreaDao; import com.example.demo.entity.Area; import com.example.demo.service.AreaService; @Service public class AreaServiceImpl implements AreaService { @Autowired private AreaDao areaDao; @Override public List<Area> getAreaList() { // 返回所有的區域信息 return areaDao.queryArea(); } @Override public Area getAreaById(int areaId) { return areaDao.queryAreaById(areaId); } @Transactional @Override public boolean addArea(Area area) { // 空值判斷,主要是判斷areaName不為空 if (area.getAreaName() != null && !"".equals(area.getAreaName())) { // 設置默認值 area.setCreateTime(new Date()); area.setLastEditTime(new Date()); try { int effectedNum = areaDao.insertArea(area); if (effectedNum > 0) { return true; } else { throw new RuntimeException("添加區域信息失敗!"); } } catch (Exception e) { throw new RuntimeException("添加區域信息失敗:" + e.toString()); } } else { throw new RuntimeException("區域信息不能為空!"); } } @Transactional @Override public boolean modifyArea(Area area) { // 空值判斷,主要是areaId不為空 if (area.getAreaId() != null && area.getAreaId() > 0) { // 設置默認值 area.setLastEditTime(new Date()); try { // 更新區域信息 int effectedNum = areaDao.updateArea(area); if (effectedNum > 0) { return true; } else { throw new RuntimeException("更新區域信息失敗!"); } } catch (Exception e) { throw new RuntimeException("更新區域信息失敗:" + e.toString()); } } else { throw new RuntimeException("區域信息不能為空!"); } } @Transactional @Override public boolean deleteArea(int areaId) { if (areaId > 0) { try { // 刪除區域信息 int effectedNum = areaDao.deleteArea(areaId); if (effectedNum > 0) { return true; } else { throw new RuntimeException("刪除區域信息失敗!"); } } catch (Exception e) { throw new RuntimeException("刪除區域信息失敗:" + e.toString()); } } else { throw new RuntimeException("區域Id不能為空!"); } } }
3.6 第五步:controller層
controller負責接收請求和響應。
代碼如下:

package com.example.demo.controller; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.example.demo.entity.Area; import com.example.demo.service.AreaService; @RestController public class AreaController { @Autowired private AreaService areaService; /** * 獲取所有的區域信息 * * @return */ @RequestMapping(value = "/listarea", method = RequestMethod.GET) private Map<String, Object> listArea() { Map<String, Object> modelMap = new HashMap<String, Object>(); List<Area> list = new ArrayList<Area>(); // 獲取區域列表 list = areaService.getAreaList(); modelMap.put("areaList", list); return modelMap; } /** * 通過區域Id獲取區域信息 * * @return */ @RequestMapping(value = "/getareabyid", method = RequestMethod.GET) private Map<String, Object> getAreaById(Integer areaId) { Map<String, Object> modelMap = new HashMap<String, Object>(); // 獲取區域信息 Area area = areaService.getAreaById(areaId); modelMap.put("area", area); return modelMap; } /** * 添加區域信息 * * @param area * @return * @throws IOException * @throws JsonMappingException * @throws JsonParseException */ @RequestMapping(value = "/addarea", method = RequestMethod.POST) private Map<String, Object> addArea(@RequestBody Area area) throws JsonParseException, JsonMappingException, IOException { Map<String, Object> modelMap = new HashMap<String, Object>(); // 添加區域信息 modelMap.put("success", areaService.addArea(area)); return modelMap; } /** * 修改區域信息,主要修改名字 * * @param area * @return * @throws IOException * @throws JsonMappingException * @throws JsonParseException */ @RequestMapping(value = "/modifyarea", method = RequestMethod.POST) private Map<String, Object> modifyArea(@RequestBody Area area) throws JsonParseException, JsonMappingException, IOException { Map<String, Object> modelMap = new HashMap<String, Object>(); // 修改區域信息 modelMap.put("success", areaService.modifyArea(area)); return modelMap; } @RequestMapping(value = "/removearea", method = RequestMethod.GET) private Map<String, Object> removeArea(Integer areaId) { Map<String, Object> modelMap = new HashMap<String, Object>(); System.out.println(areaId); // 修改區域信息 modelMap.put("success", areaService.deleteArea(areaId)); return modelMap; } }
4 運行效果