轉(zhuǎn)載請(qǐng)注明來(lái)源 賴(lài)賴(lài)的博客
導(dǎo)語(yǔ)
對(duì)接越多雕沿,耦合約松,系統(tǒng)越復(fù)雜猴仑。
如果這章學(xué)習(xí)有困難审轮,可以先參考番外 02: Spring 之使用 JAVA 操作Mysql數(shù)據(jù)庫(kù)(為何要用ORM)Spring整合 Mybatis前基礎(chǔ)
Mybatis作為最近比較流行的ORM框架(Object Relation Mapping),ORM的功能也就是把數(shù)據(jù)庫(kù)的表映射為對(duì)象便于操作辽俗。
本章介紹Mybatis與Spring的融合和推薦一種入手使用的方式疾渣,你不需要對(duì)Mybatis有很深刻的了解,只需要知道他是一個(gè)ORM框架即可崖飘,但是你需要知道數(shù)據(jù)庫(kù)的基本知識(shí)榴捡。
數(shù)據(jù)庫(kù)的使用是不可避免的,在學(xué)習(xí)本章之前朱浴,你需要:
- 了解數(shù)據(jù)庫(kù)的基本知識(shí)
- 使用過(guò)mysql數(shù)據(jù)庫(kù)
- 熟悉SQL語(yǔ)句
- 電腦已經(jīng)安裝mysql數(shù)據(jù)庫(kù)(建議學(xué)習(xí)可以使用WAMP套件)
實(shí)例
項(xiàng)目工程目錄結(jié)構(gòu)和代碼獲取地址
獲取地址(版本Log將會(huì)注明每一個(gè)版本對(duì)應(yīng)的課程)
https://github.com/laiyijie/SpringLearning
目錄結(jié)構(gòu)&數(shù)據(jù)庫(kù)
工程目錄結(jié)構(gòu)
數(shù)據(jù)庫(kù)
創(chuàng)建語(yǔ)句:
CREATE TABLE account
(
username
varchar(45) NOT NULL,
password
varchar(45) NOT NULL,
name
varchar(45) NOT NULL,
create_time
bigint(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
ALTER TABLE account
ADD PRIMARY KEY (username
);
運(yùn)行工程(與之前不同吊圾,請(qǐng)注意)
運(yùn)行方式
- 右鍵App.java
- Run as
- Java Application
運(yùn)行結(jié)果
Account [username=laiyijie, password=123456, name=賴(lài)賴(lài), create_time=1480595033430]
Account [username=laiyijie, password=123456, name=賴(lài)賴(lài), create_time=1480595033430]
項(xiàng)目詳解
從 App.java 入手:
App.java
package me.laiyijie.demo;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import me.laiyijie.demo.domain.Account;
import me.laiyijie.demo.service.UserService;
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("root-context.xml");
UserService service = context.getBean(UserService.class);
Account account = service.createAccount("laiyijie", "123456", "賴(lài)賴(lài)");
System.out.println(account);
List<Account> accounts = service.getAccountsByCreateTime(0L, System.currentTimeMillis());
for (Account account2 : accounts) {
System.out.println(account2);
}
context.close();
}
}
- 加載
ApplicationContext
- 取出
UserService
的實(shí)現(xiàn)對(duì)象 - 調(diào)用
UserService
的createAccount
方法 - 輸出
account
- 調(diào)用
UserService
的getAccountsByCreateTime
方法 - 循環(huán)輸出
accounts
- 關(guān)閉
ApplicationContext
Account
類(lèi)是一個(gè)純數(shù)據(jù)類(lèi),也就是說(shuō)翰蠢,Account
類(lèi)中的字段與數(shù)據(jù)庫(kù)中的字段完全對(duì)應(yīng):
Account.java(沒(méi)有給出 getter和setter以及toString方法)
package me.laiyijie.demo.domain;
public class Account {
private String username;
private String password;
private String name;
private Long create_time;
}
果然與數(shù)據(jù)庫(kù)中的字段完全一樣O钇埂!
CREATE TABLE `account` (
`username` varchar(45) NOT NULL,
`password` varchar(45) NOT NULL,
`name` varchar(45) NOT NULL,
`create_time` bigint(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
那讓我們繼續(xù)看看UserService都定義了一些什么:
UserService.java
package me.laiyijie.demo.service;
import java.util.List;
import me.laiyijie.demo.domain.Account;
public interface UserService {
Account createAccount(String username ,String password,String name);
List<Account> getAccountsByCreateTime(Long start,Long end);
}
定義了兩個(gè)方法
- 創(chuàng)建賬號(hào)
- 取出兩個(gè)時(shí)間之間創(chuàng)建的所有賬號(hào)
其實(shí)現(xiàn)類(lèi)為 UserServiceImpl
UserServiceImpl.java
package me.laiyijie.demo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import me.laiyijie.demo.dao.AccountMapper;
import me.laiyijie.demo.domain.Account;
import me.laiyijie.demo.domain.AccountExample;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private AccountMapper accountMapper;
public Account createAccount(String username, String password, String name) {
Account account = new Account();
account.setCreate_time(System.currentTimeMillis());
account.setName(name);
account.setPassword(password);
account.setUsername(username);
accountMapper.insert(account);
return account;
}
public List<Account> getAccountsByCreateTime(Long start, Long end) {
AccountExample accountExample = new AccountExample();
accountExample.or().andCreate_timeGreaterThan(start).andCreate_timeLessThanOrEqualTo(end);
return accountMapper.selectByExample(accountExample);
}
}
關(guān)鍵來(lái)了梁沧!
此處引入了依賴(lài) private AccountMapper accountMapper
并且調(diào)用了此接口的一些方法檀何!
我們不妨看一下這個(gè)類(lèi):
AccountMapper.java
package me.laiyijie.demo.dao;
import java.util.List;
import me.laiyijie.demo.domain.Account;
import me.laiyijie.demo.domain.AccountExample;
import org.apache.ibatis.annotations.Param;
public interface AccountMapper {
long countByExample(AccountExample example);
int deleteByExample(AccountExample example);
int deleteByPrimaryKey(String username);
int insert(Account record);
int insertSelective(Account record);
List<Account> selectByExample(AccountExample example);
Account selectByPrimaryKey(String username);
int updateByExampleSelective(@Param("record") Account record, @Param("example") AccountExample example);
int updateByExample(@Param("record") Account record, @Param("example") AccountExample example);
int updateByPrimaryKeySelective(Account record);
int updateByPrimaryKey(Account record);
}
可以看到,AccountMapper
定義了對(duì)Account數(shù)據(jù)表的所有操作(CRUD),其中有一部分以ByExample
結(jié)尾的不容易理解埃碱,我們?cè)敿?xì)講解猖辫!
List<Account> selectByExample(AccountExample example)
我們看其用法:
public List<Account> getAccountsByCreateTime(Long start, Long end) {
AccountExample accountExample = new AccountExample();
accountExample.or().andCreate_timeGreaterThan(start).andCreate_timeLessThanOrEqualTo(end);
return accountMapper.selectByExample(accountExample);
}
這段代碼摘自UserServiceImpl
中,這個(gè)方法的目的是取出start到end時(shí)間內(nèi)創(chuàng)建的所有賬號(hào)
AccountExample
的目的是為了組合一個(gè)where
語(yǔ)句砚殿,其組合出的語(yǔ)句結(jié)構(gòu)如下 where(xxx and xxx)or (xxx and xxx)
所以:
accountExample.or().andCreate_timeGreaterThan(start).andCreate_timeLessThanOrEqualTo(end);
等于
where create_time > xxx and create_time<=xxx
如果進(jìn)一步的啃憎,我們?cè)黾右恍写aaccountExample.or().andUsernameEqualTo("laiyijie");
那么就是相當(dāng)于:
accountExample.or().andCreate_timeGreaterThan(start).andCreate_timeLessThanOrEqualTo(end);
accountExample.or().andUsernameEqualTo("laiyijie");
等于
where (create_time > xxx and create_time<=xxx) or username="laiyijie"
就是如此簡(jiǎn)單!相信信息可以查看MybatisGenerator關(guān)于Example使用的文檔
說(shuō)了這么多似炎,是不是還是覺(jué)得代碼太多辛萍?
其實(shí)me.laiyijie.demo.dao
、me.laiyijie.demo.domain
和me.laiyijie.demo.Mapper
都是自動(dòng)生成的羡藐。 這個(gè)神器就是MybatisGenerator
贩毕。
也就是說(shuō),在現(xiàn)在這個(gè)項(xiàng)目中仆嗦,其實(shí)我只書(shū)寫(xiě)了UserService.java
辉阶、UserServiceImpl.java
和App.java
三個(gè)類(lèi)!
MybatisGenerator(創(chuàng)建 domain瘩扼,mapper谆甜,dao,Example對(duì)象集绰,ORM自動(dòng)解決)
介紹一下怎么使用MybatisGenerator(官方文檔位置)
- 下載MybatisGenerator的Eclipse插件
- 打開(kāi)MarketPlace并搜索mybatis并且安裝
- 配置mybatisGenerator.xml(用于配置如何生成源文件)
mybatisGenerator.xml
<?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>
<!-- 填寫(xiě)mysql-connector-java的驅(qū)動(dòng)類(lèi) -->
<classPathEntry
location="C:\Users\admin\.m2\repository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar" />
<context id="context1">
<commentGenerator>
<!-- 是否去除自動(dòng)生成的注釋 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 配置連接類(lèi)和數(shù)據(jù)庫(kù)賬號(hào)密碼 -->
<jdbcConnection connectionURL="jdbc:mysql://127.0.0.1:3306/myspring"
driverClass="com.mysql.jdbc.Driver" userId="test" password="o34rWayJPPHgudtL" />
<!-- 配置生成類(lèi)的存放包名 -->
<javaModelGenerator targetPackage="me.laiyijie.demo.domain"
targetProject="demo" />
<sqlMapGenerator targetPackage="me.laiyijie.demo.mapper"
targetProject="demo" />
<javaClientGenerator targetPackage="me.laiyijie.demo.dao"
targetProject="demo" type="XMLMAPPER" />
<!-- 需要生成表 -->
<table schema="myspring" tableName="account" domainObjectName="Account">
<property name="useActualColumnNames" value="true" />
</table>
</context>
</generatorConfiguration>
- 右鍵
mybatisGenerator.xml
> Run as> Mybatis Generator 生成成功规辱!
詳細(xì)配置請(qǐng)參考MybatisGenerator官方文檔
下面這一步就是配置Spring連接數(shù)據(jù)庫(kù):
root-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<context:component-scan base-package="me.laiyijie.demo"></context:component-scan>
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://127.0.0.1:3306/myspring"
p:username="test" p:password="o34rWayJPPHgudtL" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="mysqlDataSource" p:mapperLocations="classpath:me/laiyijie/demo/mapper/*.xml" />
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:sqlSessionFactoryBeanName="sqlSessionFactory" p:basePackage="me.laiyijie.demo.dao" />
</beans>
新增的配置的解釋如下:
-
配置數(shù)據(jù)源(數(shù)據(jù)庫(kù)賬密等)
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://127.0.0.1:3306/myspring"
p:username="test" p:password="o34rWayJPPHgudtL" /> -
配置
Mybatis
的sqlSessionFactory
和MapperScannerConfigurer
(其實(shí)就是用于掃描所有*.xml
配置文件并且生成與接口*Mapper
對(duì)應(yīng)的實(shí)現(xiàn)類(lèi)的Bean,這也是為什么可以使用@Autowired
來(lái)加載AccountMapper
這個(gè)接口的原因栽燕!<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="mysqlDataSource" p:mapperLocations="classpath:me/laiyijie/demo/mapper/*.xml" /> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" p:sqlSessionFactoryBeanName="sqlSessionFactory" p:basePackage="me.laiyijie.demo.dao" />
三條配置罕袋,一點(diǎn)兒也不麻煩!
pom.xml
<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>me.laiyijie</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- mybatis-Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
</project>
新增依賴(lài):
- spring-jdbc spring對(duì)數(shù)據(jù)庫(kù)查詢的支持
- commons-dbcp 配置數(shù)據(jù)源中的
org.apache.commons.dbcp.BasicDataSource
來(lái)源碍岔,數(shù)據(jù)連接池 - mybatis-spring
root-context.xml
中的使用的兩個(gè)類(lèi)出自這里 - mybatis mybatis框架
- mysql-connector-java 連接mysql數(shù)據(jù)庫(kù)用的驅(qū)動(dòng)
小結(jié)
- Mybatis是一種ORM框架浴讯,ORM的功能也就是把數(shù)據(jù)庫(kù)的表映射為對(duì)象便于操作。
- 通過(guò) mybatis-spring包使得Mybatis可以在Spring中使用
- 數(shù)據(jù)源的連接是依賴(lài)于實(shí)用的數(shù)據(jù)庫(kù)付秕,本文使用的Mysql因此需要引入 mysql-connector
- MybatisGenerator產(chǎn)生的類(lèi)和方法涵蓋了單表的所有操作兰珍,可以解決絕大部分?jǐn)?shù)據(jù)庫(kù)操作問(wèn)題
附:
數(shù)據(jù)源配置建議如下(解決Mysql八小時(shí)問(wèn)題以及utf-8編碼問(wèn)題):
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://127.0.0.1:3306/myspring?useUnicode=true&characterEncoding=utf8"
p:username="test" p:password="o34rWayJPPHgudtL" p:testWhileIdle="true"
p:testOnBorrow="false" p:validationQuery="SELECT 1"
p:timeBetweenEvictionRunsMillis="7200000" p:numTestsPerEvictionRun="50" />