之前的MVC,V->C->M,都是面向对象的语言,如果与面向关系的数据库相互,就会出现阻抗不匹配的问题,需要持久层提供映射,把对象的类映射成数据库中的表,把对象类中的属性映射成表中的字段,把对象和对象的关系映射成一对一、一对多、多对多的关系。
不用JDBC而使用持久层是因为它只支持本地事务,不支持两阶段提交事务。
Mybatis的前身是IBatis,之前用的多的持久化框架还有Hibernate、Oracle TopLink,CMB(来自EJB)、OJB。
-
如何构建Mybatis:
1.添加相应的jar包到pom.xml
2.配置(1)Core Config file–>sqlMapConfig.xml
(2)mapper Config file–>xxxMapper.xml
3.添加日志信息log information到工程中,特指log4j.properties
4.添加db.properties(driver,name,url.pass)到工程中新建工程:
先在pom.xml中添加mysql和mybatis依赖:
<?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>com.bit</groupId>
<artifactId>mybaitsprojects</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</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>
在resources中新建配置文件sqlMapConfig.xml:
在MySQL中新建一个数据库ming:
写sqlMapConfig.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="db.properties"/>
<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>
</environment>
</environments>
</configuration>
在resources中添加db.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ming
jdbc.username=root
jdbc.password=jdpy1229jiajia
因为是Maven,需要在pom.xml中添加:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.yml</include><!--以后会用到-->
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.yml</include><!--以后会用到-->
</includes>
</resource>
</resources>
新建一个类po(持久化对象),将此类映射到之前在数据库中新建的表:
package com.bit.po;
//持久化对象,要把这个对象放到数据库中
public class user {
//必须要有primary key
public int userID;
public String userName;
public String userAddr;
//默认的无参构造
public user()
{}
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAddr() {
return userAddr;
}
public void setUserAddr(String userAddr) {
this.userAddr = userAddr;
}
@Override
public String toString() {
return "user{" +
"userID=" + userID +
", userName='" + userName + '\'' +
", userAddr='" + userAddr + '\'' +
'}';
}
}
建立mapper.xml进行持久化,在resources中新建Directory,名为mapper:
在usermapper.xml中写:
<?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">
<!--namespace非常重要,必须有。可以区分相同id-->
<mapper namespace="test">
<!--建立映射关系:对象和数据库中的表-->
<!--需求1:根据ID进行查询-->
<select id="queryUserById" parameterType="int" resultType="com.bit.po.user">
select *from user where userid=#{value};
</select>
</mapper>
其中,select id是指整个标签。parameterType是输入参数,来自sql语句的输入参数,通过parameterType给占位符#{ }赋值。resultType是返回的值,语句执行的结果。即一个user对象值或结果集。
"#{}"代表变量的位置。如果变量是9种基本类型:byte、short、int、long、float、double、boolean、char、void,名字无所谓;如果不是基本类型,需要起名为value。
接下来进行测试:
在MybatisTest中写:
package com.bit;
import com.bit.po.user;
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.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MybatisTest {
//获取sqlSessionnfactory
private SqlSessionFactory sqlSessionFactory;
@Before
public void testInit()
{
String mybatisConfigFile="sqlMapConfig.xml";
InputStream is=null;
try {
is=Resources.getResourceAsStream(mybatisConfigFile);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
//执行相关操作
@Test
public void queryUserByID()
{
SqlSession sqlSession=sqlSessionFactory.openSession();
user user1=sqlSession.selectOne("test.queryUserById",1);
System.out.println(user1);
sqlSession.close();
}
}
加入log4j信息:
log4j.rootLogger=DEBUG, Console
#Mybatis log4j
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
运行单元测试,结果如下:
需要在核心配置文件sqlMapConfig.xml中加入映射信息:
<!--需要添加核心信息-->
<mappers>
<mapper resource="mapper/usermapper.xml"/>
</mappers>
再运行单元测试:
在之前的Spring学习中,applicationContext.xml既是Spring框架,也是Spring技术,也是Spring容器。而Mybatis的核心配置文件是sqlMapConfig.xml,配置了和数据库相关的信息,包括Driver url username 和password,还有关联的映射文件。一个SqlSessionfactory对应一个数据库,可以把sqlMapConfig.xml看作SqlSessionfactory。单元测试读取的是整个配置文件,配置文件找到映射文件,映射文件再找到里面的Statement ID,最终执行查询语句,然后把查询结果放在result中,通过sqlSession执行(增删改查)等操作,而sqlSession正是来源于sqlSessionfactory。
查询结构是个user对象,把表中的一行记录映射成了数据库中的一个类,把表中的字段userId、username、userAddr映射成po中user类对象的属性,通过get、set方法。
如果想看log4j,需要先添加log4j依赖:
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
以上是根据ID进行查询的操作,接下来,根据名字模糊查询。
能查出4条数据。
在usermap.xml中写入:
<!--需求2:根据姓名模糊查询-->
<select id="queryUserByName" parameterType="java.lang.String" resultType="com.bit.po.user">
select * from user where username like #{value};
</select>
在单元测试中写:
@Test
public void queryUserByName()
{
SqlSession sqlSession=sqlSessionFactory.openSession();
List<user> user2=sqlSession.selectList("test.queryUserByName","%vin%");
System.out.println(user2);
sqlSession.close();
运行结果为:
除了"#{}",还可以用“${}”。在usermapper中写:
<!--需求2:根据姓名模糊查询-->
<select id="queryUserByName" parameterType="java.lang.String" resultType="com.bit.po.user">
select * from user where username like '%${value}%';
</select>
在单元测试中:
List<user> user2=sqlSession.selectList("test.queryUserByName","vin");
//之前是“%vin%”
建议使用"${}"。
接下来实现添加元组的需求:
在usermapper.xml中写:
<!--需求3:添加元组-->
<insert id="addUser" parameterType="com.bit.po.user" >
insert into user(username,useraddr) value (#{userName},#{userAddr});
</insert>
username和userAddr分别是user表中的两列,同时也是po中user类对象的两个属性值,userId是自增的,所以可以给个user对象,这个user对象可以找到userName和userAddr属性。
在单元测试中写:
@Test
public void AddUser()
{
SqlSession sqlSession=sqlSessionFactory.openSession();
user user3=new user();
user3.setUserName("MMMM");
user3.setUserAddr("USA");
int flag=sqlSession.insert("test.addUser",user3);
//事务相关,除了查询操作以外,其他执行操作之后需要提交事务。
try{
sqlSession.commit();
System.out.println(flag);
}
catch (Exception ex)
{ex.printStackTrace();
//失败了要回滚事务
sqlSession.rollback();}
finally {
sqlSession.close();
}
}
运行结果为:
接下来,是修改操作:
在usermapper.xml中写:
<!--需求4:更新元组-->
<update id="updateUser" parameterType="com.bit.po.user">
update user set username=#{userName} where userid=#{userID};
</update>
(原理与添加元组同,需要注意"#{}"里面的内容要与user类的属性相对应,注意字母大小写。)
进行单元测试:
@Test
public void updateUser()
{
SqlSession sqlSession=sqlSessionFactory.openSession();
try{
user user4=new user();
user4.setUserName("HHHH");
user4.setUserID(9);
int flag=sqlSession.update("test.updateUser",user4);
//事务相关,除了查询操作以外,其他执行操作之后需要提交事务。
sqlSession.commit();
System.out.println(flag);
}
catch (Exception ex)
{ex.printStackTrace();
//失败了要回滚事务
sqlSession.rollback();}
finally {
sqlSession.close(); }
}
测试通过:
最后是删除操作:
在usermapper.xml中写:
<!--需求5:删除元组-->
<delete id="deleteUser" parameterType="com.bit.po.user">
delete from user where userid=#{userID}
</delete>
进行单元测试:
@Test
public void deleteUser()
{
SqlSession sqlSession=sqlSessionFactory.openSession();
try{
user user5=new user();
user5.setUserID(9);
int flag=sqlSession.delete("test.deleteUser",user5);
//事务相关,除了查询操作以外,其他执行操作之后需要提交事务。
sqlSession.commit();
System.out.println(flag);
}
catch (Exception ex)
{ex.printStackTrace();
//失败了要回滚事务
sqlSession.rollback();}
finally {
sqlSession.close(); }
}
也可以写成
<!--需求5:删除元组-->
<delete id="delete2User" parameterType="int">
delete from user where userid=#{myid}
</delete>
进行单元测试:
@Test
public void delete2User()
{
SqlSession sqlSession=sqlSessionFactory.openSession();
try{
int flag=sqlSession.delete("test.delete2User",8);
//事务相关,除了查询操作以外,其他执行操作之后需要提交事务。
sqlSession.commit();
System.out.println(flag);
}
catch (Exception ex)
{ex.printStackTrace();
//失败了要回滚事务
sqlSession.rollback();}
finally {
sqlSession.close(); }
}
通过测试:
新需求:Spring MVC+JDBC+单表的CRUD操作。