mybatis


ibatis 亲爹 apache 后爹 google 后后爹github

开源的持久层框架

jdbc 代码繁琐 手写sql 速度快,性能好 就是麻烦

编程步骤
1、导包
2、添加mybatis配置文件
3、写实体类
4、写映射文件,修改配置文件,指定英文文件的位置
5、调用mybatis 提供的API SqlSession 提供的方法来访问数据库


1、导包
mybatis
mysql

2、配置文件

<?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> 
<!-- 环境:配置mybatis的环境 --> 
<environments default="environment"> 
<!-- 环境变量:可以配置多个环境变量,比如使用多数据源时,就需要配置多个环境变量 --> 
<environment id="environment"> 
<!-- 事务管理器 --> 
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 --> 
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://172.29.12.158:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="username" value="zongxuan"/>
<property name="password" value="zongxuan"/>
</dataSource> 
</environment> 
</environments> 
<!-- 映射器:指定映射文件或者映射类 --> 
<mappers>
<mapper resource="entity/MepMapper.xml"/>
</mappers> 
</configuration>

 

3、实体类的属性名与表的字段表要求一样 大小写无所谓

package entity;

public class Emp {
    private Integer id;
    private String name;
    private Double age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getAge() {
        return age;
    }

    public void setAge(Double age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Emp [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
}

 

4、写实体类

<?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="test"> 
<!-- 
id 唯一 
parameterType 参数类型
#{} 实体类的属性
-->
<insert id="save" parameterType="entity.Emp">
INSERT INTO emp2(name,age) VALUES(#{name},#{age})
</insert>

<!-- 
resultType:返回结果的类型 最终的
-->
<select id="findAll" resultType="entity.Emp">
SELECT * FROM emp2
</select>

<select id="findById" parameterType="int" resultType="entity.Emp">
SELECT * FROM emp2 WHERE id=#{id}
</select>

<update id="modify" parameterType="entity.Emp">
UPDATE emp2 SET name=#{name},age=#{age} WHERE id=#{id}
</update>

<delete id="delete" parameterType="int">
DELETE FROM emp2 WHERE id=#{id}
</delete>

</mapper> 

5、调用mybatis

 

package testCase;

import java.util.List;

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 entity.Emp;

public class TestMybats {

    private SqlSession ss;

    @Before

    public void init() {
        SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
        SqlSessionFactory ssf = ssfb.build(TestMybats.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml"));
        ss = ssf.openSession();
    }

    @Test
    public void t1() {
        Emp emp = new Emp();
        emp.setName("李四");
        emp.setAge(new Double("22"));
        ss.insert("test.save", emp);
        ss.commit();
        ss.close();
    }

    @Test
    public void t2() {
        List<Emp> emps = ss.selectList("test.findAll");
        System.out.println(emps);
        ss.close();

    }

    @Test
    public void t3() {
        Emp emp = ss.selectOne("test.findById", 4);
        System.out.println(emp);
        ss.close();
    }

    @Test
    public void t4() {
        Emp emp = ss.selectOne("test.findById", 4);
        emp.setName("王五");
        ss.update("test.modify", emp);
        ss.commit();
        ss.close();

    }

    @Test
    public void t5() {
        ss.delete("test.delete", 1);
        ss.commit();
        ss.close();
    }

}

 

返回Map类型的结果

mybatis 会将查询结果先封装到一个map对象里面 字段名作为key 字段值作为value
然后再将map对象中的数据添加到实体对象里面

<select id="findById2" parameterType="int" resultType="map">
SELECT * FROM dept WHERE id=#{id}
</select>

 

@Test
public void t6() {
  Map data = ss.selectOne("dept.findById2",3);
  System.out.println(data);
  System.out.println(data.get("dname"));
  ss.close();
}

 

 

属性名和字段名不一样
1、在mybatis 映射文件SQL 中使用别名
2、使用ResultMap

1

2、

CREATE TABLE `emp2` ( 
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`name` varchar(30) DEFAULT NULL, 
`age` int(11) DEFAULT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 

 

package entity;

public class Emp2 {
    private Integer emapNo;
    private String ename;
    private Double age;

    public Integer getEmapNo() {
        return emapNo;
    }

    public void setEmapNo(Integer emapNo) {
        this.emapNo = emapNo;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Double getAge() {
        return age;
    }

    public void setAge(Double age) {
        this.age = age;
    }

@Override
public String toString() {
return "Emp2 [emapNo=" + emapNo + ", ename=" + ename + ", age=" + age + "]";
}
}
<!-- 使用ResultMap 解决表的字段名和实体类的属性名不一致的情况 -->
<!-- 处理表的字段名和实体类的属性名的对应关系 -->

<resultMap type="entity.Emp2" id="emp2Map">
<result property="ename" column="name" />
<result property="emapNo" column="id" />
</resultMap>

<select id="findById2" parameterType="int" resultMap="emp2Map">
SELECT *
FROM emp2 WHERE id=#{id}
</select>

 

@Test
public void t6() {
  Emp2 emp = ss.selectOne("test.findById2",3);
  System.out.println(emp);
  ss.close();
}

 

 

Mapper 映射器
符合映射文件的接口
mybatis 会自动实现一个符合该接口要求的对象
要求:
a、接口方法的名称与映射中的sql的id要一样
b、方法的参数类型要与映射文件中的parameterType一致
c、方法的返回类型要与映射文件当中的resultType一致
映射文件的命名空间namespace要等于Mapper映射器的全限定名

 

<?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> 
<!-- 环境:配置mybatis的环境 --> 
<environments default="environment"> 
<!-- 环境变量:可以配置多个环境变量,比如使用多数据源时,就需要配置多个环境变量 --> 
<environment id="environment"> 
<!-- 事务管理器 --> 
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 --> 
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://172.29.12.158:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="username" value="zongxuan"/>
<property name="password" value="zongxuan"/>
</dataSource> 
</environment> 
</environments> 
<!-- 映射器:指定映射文件或者映射类 --> 
<mappers>
<mapper resource="entity/EmpMapper.xml"/>
</mappers> 
</configuration>

 

 

package com.stevezong.mybatis.entity.dao;

import java.util.List;
import java.util.Map;

import entity.Emp;
import entity.Emp2;

/**
 * Mapper映射器 就是一个接口
 * 
 * @author steve
 *
 */

public interface EmpDAO {
    void save(Emp emp);

    List<Emp> findAll();

    Emp findById(int id);

    void delete(int id);

    void modify(Emp emp);

    Emp2 findById2(int id);
}

 

<?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.stevezong.mybatis.entity.dao.EmpDAO">
    <!-- id 唯一 parameterType 参数类型 #{} 实体类的属性 -->
    <insert id="save" parameterType="entity.Emp">
        INSERT INTO emp2(name,age)
        VALUES(#{name},#{age})
    </insert>

    <!-- resultType:返回结果的类型 最终的 -->
    <select id="findAll" resultType="entity.Emp">
        SELECT * FROM emp2
    </select>

    <select id="findById" parameterType="int" resultType="entity.Emp">
        SELECT *
        FROM emp2 WHERE id=#{id}
    </select>

    <update id="modify" parameterType="entity.Emp">
        UPDATE emp2 SET
        name=#{name},age=#{age} WHERE id=#{id}
    </update>

    <delete id="delete" parameterType="int">
        DELETE FROM emp2 WHERE
        id=#{id}
    </delete>

    <!-- 使用ResultMap 解决表的字段名和实体类的属性名不一致的情况 -->
    <!-- 处理表的字段名和实体类的属性名的对应关系 -->
    <!-- property对应javabean的属性名,column对应数据库字段名 -->
    <resultMap type="entity.Emp2" id="emp2Map">
        <result property="ename" column="name" />
        <result property="emapNo" column="id" />
    </resultMap>

    <select id="findById2" parameterType="int" resultMap="emp2Map">
        SELECT *
        FROM emp2 WHERE id=#{id}
    </select>
</mapper>

 

 

package testCase;

import java.util.List;

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 com.stevezong.mybatis.entity.dao.EmpDAO;

import entity.Emp;
import entity.Emp2;

public class TestCase {

    private SqlSession ss;

    @Before
    public void init() {
        SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
        SqlSessionFactory ssf = ssfb.build(TestCase.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml"));
        ss = ssf.openSession();
    }

    @Test
    public void t1() {
        /**
         * getMapper 方法返回一个符合Mapper映射器(EmpDAO)要求的对象
         * 
         */
        EmpDAO dao = ss.getMapper(EmpDAO.class);
        Emp emp = new Emp();
        emp.setName("王八");
        emp.setAge(new Double(22));
        dao.save(emp);
        ss.commit();
        List<Emp> emps = dao.findAll();
        System.out.println(emps);
        Emp emp2 = dao.findById(4);
        System.out.println(emp2);
        dao.delete(2);
        ss.commit();
        Emp emp3 = new Emp();
        emp3.setName("丽丽");
        emp3.setAge(new Double(88));
        emp3.setId(10);
        dao.modify(emp3);
        ss.commit();
        Emp2 emp4 = dao.findById2(3);
        System.out.println(emp4);
        ss.close();

    }

}

 


spring 集成 mybatis
1、导包
spring-webmvc
mybatis
mybatis-spring
spring-jdbc
mysql
dbcp(c3p0)
2、添加spring的配置文件
mybatis 的配置信息可以添加到spring的配置文件中
3、实体类
entity
4、映射文件
XML
5、Mapper映射器
DAO接口
6、在spring 的配置文件当中,添加MapperScannerConfigurer bean 该bean 负责条用SqlSession的getMapper方法
创建符合Mapper映射器要求的对象,
该bean会将这个对象添加到spring容器里面(默认额id 是首字母小写之后的接口名,也可以在Mapper使用@Rerspository来设定id)


1、

<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.stevezong</groupId>
    <artifactId>mybataiszx</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>3.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>commons-DBCP</groupId>
            <artifactId>commons-DBCP</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>

</project>

 


2

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">

    <!-- mysql 信息 -->
    <util:properties id="dbInfo">
        <prop key="user">zongxuan</prop>
        <prop key="password">zongxuan</prop>
        <prop key="url">jdbc:mysql://172.29.12.158:3306/test?useUnicode=true&amp;characterEncoding=utf8
        </prop>
        <prop key="driver">com.mysql.jdbc.Driver</prop>
        <prop key="initialSize">10</prop>
        <prop key="maxActive">500</prop>
    </util:properties>

    <!-- 配置连接池 -->
    <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="#{dbInfo.driver}"></property>
        <property name="url" value="#{dbInfo.url}"></property>
        <property name="username" value="#{dbInfo.user}"></property>
        <property name="password" value="#{dbInfo.password}"></property>
        <property name="initialSize" value="#{dbInfo.initialSize}"></property>
        <property name="maxActive" value="#{dbInfo.maxActive}"></property>
    </bean>

    <!-- 配置SqlSessionFactoryBean mybatis-spring包中 spring 集成mybatis 不在需要mybatis 
        的配置文件,(使用SqlSessionFactoryBean来代替mybatis的配置文件) -->
    <bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入连接池, 不再使用mybatis 自带的连接池,而是使用spring管理的连接池 -->
        <property name="dataSource" ref="ds"></property>
        <property name="mapperLocations" value="classpath:entity/*.xml"></property>
    </bean>

    <!-- 配置MapperScannerConfigurer 负责扫描指定包下面的所有的Mapper映射器然后生成符合这些映射器要求的对象 其实,就是调用SqlSession的getMapper方法 
        另外,还会将这个对象添加到spring容器里面 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定Mapper映射器所在的包 -->
        <property name="basePackage" value="dao"></property>
        <!-- 只扫描特定的接口 自己开发注解 自动扫描包下所有接口 遇到带注解标记的将对应对象注册 不加不注解 不会注册 -->
        <property name="annotationClass" value="annotations.MyBatisRepository"></property>
    </bean>

</beans>

 

3

package entity;

public class Emp {
    private Integer id;
    private String name;
    private Double age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getAge() {
        return age;
    }

    public void setAge(Double age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Emp [id=" + id + ", name=" + name + ", age=" + age + "]";
    }

}

 

4

<?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="dao.EmpDAO">
    <!-- id 唯一 parameterType 参数类型 #{} 实体类的属性 -->
    <insert id="save" parameterType="entity.Emp">
        INSERT INTO emp2(name,age)
        VALUES(#{name},#{age})
    </insert>

    <!-- resultType:返回结果的类型 最终的 -->
    <select id="findAll" resultType="entity.Emp">
        SELECT * FROM emp2
    </select>

    <select id="findById" parameterType="int" resultType="entity.Emp">
        SELECT *
        FROM emp2 WHERE id=#{id}
    </select>

    <update id="modify" parameterType="entity.Emp">
        UPDATE emp2 SET
        name=#{name},age=#{age} WHERE id=#{id}
    </update>

    <delete id="delete" parameterType="int">
        DELETE FROM emp2 WHERE
        id=#{id}
    </delete>

    <!-- 使用ResultMap 解决表的字段名和实体类的属性名不一致的情况 -->
    <!-- 处理表的字段名和实体类的属性名的对应关系 -->

    <resultMap type="entity.Emp2" id="emp2Map">
        <result property="ename" column="name" />
        <result property="emapNo" column="id" />
    </resultMap>

    <select id="findById2" parameterType="int" resultMap="emp2Map">
        SELECT *
        FROM emp2 WHERE id=#{id}
    </select>
</mapper>

 

5

package dao;

import java.util.List;
import java.util.Map;

import annotations.MyBatisRepository;
import entity.Emp;
import entity.Emp2;

/**
* Mapper映射器 就是一个接口
* @author steve
*
*/

@MyBatisRepository
public interface EmpDAO {
void save(Emp emp);
List<Emp> findAll();
Emp findById(int id);
void delete(int id);
void modify(Emp emp);
Emp2 findById2(int id);
}

package annotations;

public @interface MyBatisRepository {

}
package test;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import dao.EmpDAO;
import entity.Emp;

public class TestCase {

    private ApplicationContext ac;
    private EmpDAO dao;

    @Before
    public void init() {
        ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        dao = ac.getBean("empDAO", EmpDAO.class);
    }

    @Test
    public void t1() {
        List<Emp> emps = dao.findAll();
        System.out.println(emps);
    }

    @Test
    public void t2() {
        Emp emp = dao.findById(5);
        System.out.println(emp);
    }

}

 

6

mybatis 关联映射
将数据库中有关联关系的表 以实体对象引用的方法体现出来
如:在User 有Book
class User{
private List<Book> books;
}

class Book{
private User user;
}
关联的方式:

关联单个对象
Book 中
关联多个对象
User 中

在业务需要对数据库进行关联查询的时候
可以通过一条sql 语句完成关联查询,也可以通过两条sql语句进行关联查询
使用一条语句完成 语句复杂,配置简单 与数据库交互一次
使用两条语句完成 语句简单,配置复杂 与数据库交互两次
1、实体类
2、定义Dao接口
配置Mapper



关联多个对象

1、


package com.stevezong.cloud_note.entity;

import java.io.Serializable;
import java.util.List;

/*
* 类属性名和属性数据类型
* 与数据库中的保持一致
* 
*/
public class User implements Serializable {
    private String cn_user_id;
    private String cn_user_name;
    private String cn_user_password;
    private String cn_user_token;
    private String cn_user_nick;
    private List<Book> books;

    public String getCn_user_id() {
        return cn_user_id;
    }

    public void setCn_user_id(String cn_user_id) {
        this.cn_user_id = cn_user_id;
    }

    public String getCn_user_name() {
        return cn_user_name;
    }

    public void setCn_user_name(String cn_user_name) {
        this.cn_user_name = cn_user_name;
    }

    public String getCn_user_password() {
        return cn_user_password;
    }

    public void setCn_user_password(String cn_user_password) {
        this.cn_user_password = cn_user_password;
    }

    public String getCn_user_token() {
        return cn_user_token;
    }

    public void setCn_user_token(String cn_user_token) {
        this.cn_user_token = cn_user_token;
    }

    public String getCn_user_nick() {
        return cn_user_nick;
    }

    public void setCn_user_nick(String cn_user_nick) {
        this.cn_user_nick = cn_user_nick;
    }

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    @Override
    public String toString() {
        return "User [cn_user_id=" + cn_user_id + ", cn_user_name=" + cn_user_name + ", cn_user_password="
                + cn_user_password + ", cn_user_token=" + cn_user_token + ", cn_user_nick=" + cn_user_nick + ", books="
                + books + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((books == null) ? 0 : books.hashCode());
        result = prime * result + ((cn_user_id == null) ? 0 : cn_user_id.hashCode());
        result = prime * result + ((cn_user_name == null) ? 0 : cn_user_name.hashCode());
        result = prime * result + ((cn_user_nick == null) ? 0 : cn_user_nick.hashCode());
        result = prime * result + ((cn_user_password == null) ? 0 : cn_user_password.hashCode());
        result = prime * result + ((cn_user_token == null) ? 0 : cn_user_token.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (books == null) {
            if (other.books != null)
                return false;
        } else if (!books.equals(other.books))
            return false;
        if (cn_user_id == null) {
            if (other.cn_user_id != null)
                return false;
        } else if (!cn_user_id.equals(other.cn_user_id))
            return false;
        if (cn_user_name == null) {
            if (other.cn_user_name != null)
                return false;
        } else if (!cn_user_name.equals(other.cn_user_name))
            return false;
        if (cn_user_nick == null) {
            if (other.cn_user_nick != null)
                return false;
        } else if (!cn_user_nick.equals(other.cn_user_nick))
            return false;
        if (cn_user_password == null) {
            if (other.cn_user_password != null)
                return false;
        } else if (!cn_user_password.equals(other.cn_user_password))
            return false;
        if (cn_user_token == null) {
            if (other.cn_user_token != null)
                return false;
        } else if (!cn_user_token.equals(other.cn_user_token))
            return false;
        return true;
    }

}


2

package com.stevezong.cloud_note.dao;

import com.stevezong.cloud_note.entity.User;

public interface RelationDao {
    public User fundUserAndBooks(String userId);
}

 

package com.stevezong.cloud_note.dao;

import com.stevezong.cloud_note.entity.User;

public interface RelationDao {
    public User findUserAndBooks(String userId);
}
<!----------------------------------------------------------------------------------------------------------------------------------------- -->
<!-- 使用两条sql 语句加载数据 -->
<select id="findUserAndBooks" parameterType="String" resultMap="userMap1">
    SELECT * FROM cn_user WHERE cn_user_id=#{userId}
</select>
<resultMap id="userMap1" type="com.stevezong.cloud_note.entity.User">
    <id property="cn_user_id" column="cn_user_id" />
    <result property="cn_user_name" column="cn_user_name" />
    <!-- 指定books属性 是一个list集合 返回类型 泛型类型 外键 -->
    <collection property="books" javaType="java.util.List"
        ofType="com.stevezong.cloud_note.entity.Book" select="findBooks"
        column="cn_user_id">
    </collection>
</resultMap>
<select id="findBooks" parameterType="String"
    resultType="com.stevezong.cloud_note.entity.Book">
    SELECT * FROM cn_notebook WHERE cn_user_id=#{userId}
</select>

<!----------------------------------------------------------------------------------------------------------------------------------------- -->

<!-- 一条sql加载User -->
<select id="findUserAndBooks1" parameterType="String" resultMap="userMap2">
    SELECT * FROM cn_user u JOIN cn_notebook b
    ON(u.cn_user_id=b.cn_user_id) WHERE u.cn_user_id=#{userId}
</select>

<resultMap id="userMap2" type="com.stevezong.cloud_note.entity.User">
    <!-- 定义cn_user 字段装在,不能省略 -->
    <id property="cn_user_id" column="cn_user_id" />
    <result property="cn_user_name" column="cn_user_name" />
    <result property="cn_user_password" column="cn_user_password" />
    <result property="cn_user_token" column="cn_user_token" />
    <result property="cn_user_nick" column="cn_user_nick" />
    <collection property="books" javaType="java.util.List"
        ofType="com.stevezong.cloud_note.entity.Book">
        <id property="cn_notebook_id" column="cn_notebook_id" />
        <result property="cn_user_id" column="cn_user_id" />
        <result property="cn_notebook_type_id" column="cn_notebook_type_id" />
        <result property="cn_notebook_name" column="cn_notebook_name" />
        <result property="cn_notebook_desc" column="cn_notebook_desc" />
        <result property="cn_notebook_createtime" column="cn_notebook_createtime" />
    </collection>
</resultMap>
<!----------------------------------------------------------------------------------------------------------------------------------------- -->

 

@Test
public void t1() {
  User user = dao.findUserAndBooks("48595f52-b22c-4485-9244-f4004255b972");
  //User user = dao.findUserAndBooks1("48595f52-b22c-4485-9244-f4004255b972");
  System.out.println(user);
  System.out.println(user.getCn_user_name());
  System.out.println(user.getBooks().size());
  for(Book sub:user.getBooks()) {
    System.out.println(sub);
  }
}    

关联单个对象

通过查询笔记信心,关联用户信息

package com.stevezong.cloud_note.entity;

import java.io.Serializable;
import java.sql.Timestamp;

public class Book implements Serializable {
    private String cn_notebook_id;
    private String cn_user_id;
    private String cn_notebook_type_id;
    private String cn_notebook_name;
    private String cn_notebook_desc;
    private Timestamp cn_notebook_createtime;
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getCn_notebook_id() {
        return cn_notebook_id;
    }

    public void setCn_notebook_id(String cn_notebook_id) {
        this.cn_notebook_id = cn_notebook_id;
    }

    public String getCn_user_id() {
        return cn_user_id;
    }

    public void setCn_user_id(String cn_user_id) {
        this.cn_user_id = cn_user_id;
    }

    public String getCn_notebook_type_id() {
        return cn_notebook_type_id;
    }

    public void setCn_notebook_type_id(String cn_notebook_type_id) {
        this.cn_notebook_type_id = cn_notebook_type_id;
    }

    public String getCn_notebook_name() {
        return cn_notebook_name;
    }

    public void setCn_notebook_name(String cn_notebook_name) {
        this.cn_notebook_name = cn_notebook_name;
    }

    public String getCn_notebook_desc() {
        return cn_notebook_desc;
    }

    public void setCn_notebook_desc(String cn_notebook_desc) {
        this.cn_notebook_desc = cn_notebook_desc;
    }

    public Timestamp getCn_notebook_createtime() {
        return cn_notebook_createtime;
    }

    public void setCn_notebook_createtime(Timestamp cn_notebook_createtime) {
        this.cn_notebook_createtime = cn_notebook_createtime;
    }

    @Override
    public String toString() {
        return "Book [cn_notebook_id=" + cn_notebook_id + ", cn_user_id=" + cn_user_id + ", cn_notebook_type_id="
                + cn_notebook_type_id + ", cn_notebook_name=" + cn_notebook_name + ", cn_notebook_desc="
                + cn_notebook_desc + ", cn_notebook_createtime=" + cn_notebook_createtime + ", user=" + user + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((cn_notebook_createtime == null) ? 0 : cn_notebook_createtime.hashCode());
        result = prime * result + ((cn_notebook_desc == null) ? 0 : cn_notebook_desc.hashCode());
        result = prime * result + ((cn_notebook_id == null) ? 0 : cn_notebook_id.hashCode());
        result = prime * result + ((cn_notebook_name == null) ? 0 : cn_notebook_name.hashCode());
        result = prime * result + ((cn_notebook_type_id == null) ? 0 : cn_notebook_type_id.hashCode());
        result = prime * result + ((cn_user_id == null) ? 0 : cn_user_id.hashCode());
        result = prime * result + ((user == null) ? 0 : user.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Book other = (Book) obj;
        if (cn_notebook_createtime == null) {
            if (other.cn_notebook_createtime != null)
                return false;
        } else if (!cn_notebook_createtime.equals(other.cn_notebook_createtime))
            return false;
        if (cn_notebook_desc == null) {
            if (other.cn_notebook_desc != null)
                return false;
        } else if (!cn_notebook_desc.equals(other.cn_notebook_desc))
            return false;
        if (cn_notebook_id == null) {
            if (other.cn_notebook_id != null)
                return false;
        } else if (!cn_notebook_id.equals(other.cn_notebook_id))
            return false;
        if (cn_notebook_name == null) {
            if (other.cn_notebook_name != null)
                return false;
        } else if (!cn_notebook_name.equals(other.cn_notebook_name))
            return false;
        if (cn_notebook_type_id == null) {
            if (other.cn_notebook_type_id != null)
                return false;
        } else if (!cn_notebook_type_id.equals(other.cn_notebook_type_id))
            return false;
        if (cn_user_id == null) {
            if (other.cn_user_id != null)
                return false;
        } else if (!cn_user_id.equals(other.cn_user_id))
            return false;
        if (user == null) {
            if (other.user != null)
                return false;
        } else if (!user.equals(other.user))
            return false;
        return true;
    }

}
package com.stevezong.cloud_note.dao;

import java.util.List;

import com.stevezong.cloud_note.entity.Book;
import com.stevezong.cloud_note.entity.User;

public interface RelationDao {
    public User findUserAndBooks(String userId);
    public User findUserAndBooks1(String userId);
    public List<Book> findBookAndUser();
}

 

<!-- 两条语句加载book和关联的User信息 -->
<select id="findBookAndUser" resultMap="bookMap">
SELECT * FROM cn_notebook
</select>
<resultMap id="bookMap" type="com.stevezong.cloud_note.entity.Book">
<association property="user" javaType="com.stevezong.cloud_note.entity.User" select="findUser" column="cn_user_id"></association>
</resultMap>
<select id="findUser" resultType="com.stevezong.cloud_note.entity.User" parameterType="String">
SELECT * FROM cn_user WHERE cn_user_id=#{id}
</select>



<!-- 一条语句加载book和关联的User信息 -->
<select id="findBookAndUser1" resultMap="bookMap1">
SELECT * FROM cn_notebook nb JOIN cn_user u ON (nb.cn_user_id=u.cn_user_id) 
</select>

<resultMap id="bookMap1" type="com.stevezong.cloud_note.entity.Book">
<id property="cn_notebook_id" column="cn_notebook_id"/>
<result property="cn_user_id" column="cn_user_id"/>
<result property="cn_notebook_type_id" column="cn_notebook_type_id"/>
<result property="cn_notebook_name" column="cn_notebook_name"/>
<result property="cn_notebook_desc" column="cn_notebook_desc"/>
<result property="cn_notebook_createtime" column="cn_notebook_createtime"/>
<collection property="user" javaType="com.stevezong.cloud_note.entity.User">
<id property="cn_user_id" column="cn_user_id"/>
<result property="cn_user_name" column="cn_user_name"/>
<result property="cn_user_password" column="cn_user_password"/>
<result property="cn_user_token" column="cn_user_token"/>
<result property="cn_user_nick" column="cn_user_nick"/>
</collection>
</resultMap>

 

@Test
public void t2() {
    List<Book> books = dao.findBookAndUser();
    for(Book sub:books) {
        System.out.println(sub.getUser());
    }
}    

 

在开发中碰到用户注册的功能需要用到用户ID,但是用户ID是数据库自增生成的,这种情况上网查询后使用下面的方式配置mybatis的insert语句可以解决:
在库即可使用子层或者序列作为主键值是如何在insert执行后 立刻获取ID值

<insert id="insert" keyProperty="id" useGeneratedKeys="true" parameterType="com.demo.domain.User">
insert into User_t(name,age,addr) values(#{name},#{age},#{addr})
</insert>

 

 

@Override
public int insert(User user) {
    int insertNum = Integer.parseInt(userMapper.insert(user) + "");
    Long id = user.getId();//该对象的自增ID
    return insertNum;
}

 



动态SQL
if
choose
trim
foreach
when

 

<update id="updateNoteByMap" parameterType="map">
UPDATE 
cn_note
SET
<trim suffixOverrides=",">
<if test="title != null">
cn_note_title=#{title},
</if>
<if test="body != null">
cn_note_body=#{body},
</if>
<choose>
<when test="time != null">
cn_note_last_modify_time=#{time}
</when>
<otherwise>
cn_note_last_modify_time=UNIX_TIMESTAMP()
</otherwise>    
</choose>
</trim>
WHERE 
cn_note_id=#{noteId}
</update>

 

 

<delete id="deleteNotes" parameterType="map">
DELETE FROM cn_note
WHERE 
<if test="status != null">
cn_note_status_id=#{status} AND
</if>
cn_note_id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>


#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。

#{} 占位符
SELECT
*
FROM
emp
WHERE
name=#{name}
SELECT * FROM emp WHERE name ='张三'
${} 字符串拼接
SELECT
*
FROM
emp
WHERE
name LIKE '%${name}%'
SELECT * FROM emp WHERE name LIKE '%张三%'

在使用#{} 的时候 里面可以随便写 #{v},#{value},#{hhhg},#{asdf},#{bbb},#{aaaa},#{name}
在使用${} 的事件 里面只能用 value => ${value}



1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中


selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查询一条或多条记录。


mysql自增主键返回
查询id的sql
SELECT LAST_INSERT_ID()

通过修改User.xml映射文件,可以将mysql自增主键返回:
如下添加selectKey 标签

<!-- 保存用户 -->
<insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
<!-- selectKey 标签实现主键返回 -->
<!-- keyColumn:主键对应的表中的哪一列 -->
<!-- keyProperty:主键对应的pojo中的哪一个属性 -->
<!-- order:设置在执行insert语句前执行查询id的sql,孩纸在执行insert语句之后执行查询id的sql -->
<!-- resultType:设置返回的id的类型 -->
<selectKey keyColumn="id" keyProperty="id" order="AFTER"
resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO `user`
(username,birthday,sex,address) VALUES
(#{username},#{birthday},#{sex},#{address})
</insert>

 

LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
在java代码中 直接 user.getId();就可以获取到Id的值了

Mysql使用 uuid实现主键
需要增加通过select uuid()得到uuid值

<!-- 保存用户 -->
<insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
<!-- selectKey 标签实现主键返回 -->
<!-- keyColumn:主键对应的表中的哪一列 -->
<!-- keyProperty:主键对应的pojo中的哪一个属性 -->
<!-- order:设置在执行insert语句前执行查询id的sql,在执行insert语句之后执行查询id的sql -->
<!-- resultType:设置返回的id的类型 -->
<selectKey keyColumn="id" keyProperty="id" order="BEFORE"
resultType="string">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO `user`
(username,birthday,sex,address) VALUES
(#{username},#{birthday},#{sex},#{address})
</insert>

 

注意这里使用的order是“BEFORE”
在java代码中 直接 user.getId();就可以获取到Id的值了

 

mybatis与hibernate不同
Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。

 

SqlMapConfig.xml中配置的内容和顺序如下:

properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)

 

 

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
WHERE 1=1
<if test="sex != null and sex != ''">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</select>

 

升级

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
<!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>

 

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
再次升级

片段,如下:

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
<!-- SELECT id, username, birthday, sex, address FROM `user` -->
<!-- 使用include标签加载sql片段;refid是sql片段id -->
SELECT <include refid="userFields" /> FROM `user`
<!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>

<!-- 声明sql片段 -->
<sql id="userFields">
id, username, birthday, sex, address
</sql>

 

 

<!-- 根据ids查询用户 -->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
SELECT * FROM `user`
<where>
<!-- foreach标签,进行遍历 -->
<!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
<!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 -->
<foreach collection="ids" item="item" open="id IN (" close=")"
separator=",">
#{item}
</foreach>
</where>
</select>

 

在 多个id 使用 int[] ids = new int[] {1,2,3};
collection 的值就必须要用array 规定

<select id="queryUserByIds" parameterType="queryVo" resultType="user">
SELECT * FROM `user`
<where>
<!-- foreach标签,进行遍历 -->
<!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
<!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 -->
<foreach collection="array" item="item" open="id IN (" close=")"
separator=",">
#{item}
</foreach>
</where>
</select>

 

在使用 list的时候 值就是用 list

 

mybatis 自带的查询条件
TbItemExample example = new TbItemExample();//逆向工程生成的
Criteria criteria = example.createCriteria();

 

posted on 2018-10-10 11:44  浪漫的偷笑  阅读(151)  评论(0编辑  收藏  举报