Mybatis

Mybatis快速入門

(部分代碼使用項目不同)

概述

Mybatis是一個持久層框架,用java編寫
它封裝了jdbc操作的許多細節,使開發者只需要關注sql語句本身,無需關注註冊驅動,創建連接等繁雜過程
它使用了ORM思想實現了結果集的封裝

ORM:
Object Relational Mapping 對象關係映射
對象指面向對象
關係指關係型數據庫
Java到MySql的映射,開發者可以以面向對象的思想來管理數據庫

Mybatis是一個實現了數據庫持久化的開源框架,簡單理解就是對JDBC進行封裝

​ 簡單的說:

​ 就是把數據庫表和實體類及實體類的屬性對應起來,讓我們可以操作實體類就實現操作數據庫表

​ 表 類

​ user user

​ id userId

​ user_name userName

實體類中的屬性和數據庫的字段名稱保持一致

優點:
1.與JDBC相比,減少了50%以上的代碼量。
2.MyBatis是最簡單的持久化框架,小巧並且簡單易學。
3.MyBatis相當靈活,不會對應用程序或者數據庫的現在設計強加任何影響,SQL寫在XML裏,從程序代碼中徹底分離,降低耦合度,便於統一管理和優化,並可重用。
4.提供XML標籤,支持編寫動態SQL語句。
5.提供映射標籤,支持對象與數據庫的ORM字段關係映射。

缺點:
1.SQL語句的編寫工作量較大,尤其是字段多,關聯表多時,更是如此,對開發人員編寫SQL語句的功底有一定要求。
2.SQL語句依賴於數據庫,導致數據庫移植性差,不能隨意更換數據庫。

  • SqlSessionFactoryBuilder

    build()

  • SqlSessionFactory

    openSession()

  • SqlSession

入門

  • 新建Maven工程,pom.xml
<dependencies>

 <dependency>

   <group>org.mybatis</group>

   <artifactId>mybatis</artifactld>

   <version>3.4.5</version>

 </dependency>

 

</dependencies>
  • 新建數據表

    use mybatis;
    create table t_account(
      id int primary key auto_increment,
      usename varchar(11),
      password varchar(11),
      age int
    )
    
  • 新建數據庫實體類

    package com.zhh.entity;
    import lombok.Data;
    @Data
    public class Account {
        private long id;
        private String username;
        private String password;
        private int age;
    }
    
  • 創建MyBatis的配置文件Config.xml文件名可自定義,在resources中創建

    <?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運行環境-->
        <enviroments default="development">
            <enviroment id="development">
                <!--配置JDBC事務管理-->
                <transactionManager type="JDBC"></transactionManager>
                <!--POOLED配置JDBC數據源連接池-->
                <dataSource type="POOLED">
                  <property name="driver" value="com.mysql.jdbc.Driver"></property>
                  <property name="url" value="jdbc:mysql://localhost:3306/webshop?useUnicode=true&characterEncoding=utf8"></property>
                  <property name="username" value="root"></property>
                  <property name="password" value="123456"></property>
                
                </dataSource>
            </enviroment>
        </enviroments>
    </configuration>
    

MyBatis開發方式

使用原生接口

Mybatis框架需要開發者自定義SQL語句,寫在Mapper.xml文件中,實際開發中,會爲每個實體類創建對應的Mapper.xml,定義管理該對象數據的SQL.

AccountMapper.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:命名空間,用於隔離sql,還有一個很重要的作用,後面會講 -->
<mapper namespace="com.iweb.dao.IUserDao">
    <!-- id:statement的id 或者叫做sql的id-->
    <!-- parameterType:聲明輸入參數的類型 -->
    <!-- resultType:聲明輸出結果的類型,應該填寫pojo的全路徑 -->
    <!-- #{}:輸入參數的佔位符,相當於jdbc的? -->

    <!-- 通過id查詢一個用戶 -->
    <select id="findAll" resultType="com.iweb.domain.User">
		select * from user;
	</select>
    
    <!--四種常用標籤-->
    <insert id="save" parameterType="com.zhh.entity.Account">
    insert into t_account(username,password,age)values(#{username},#{password},#{age})
    </insert>
    <update id=""></update>
    <delete id=""></delete>
    <select id=""></select>

</mapper>

  • namespace通常設置爲文件所在包+文件名的形式
  • id是實際調用Mybatis方法時需要用到的參數
  • parameterType是調用對應方法時參數的數據類型

在全局配置文件config.xml中註冊AccountMapper.xml註冊xml

resource後寫上文件路徑,注意此時用斜槓不要用點,因爲會引起衝突

<!--註冊AccountMapper.xml-->
<mappers>
  <mapper resource="com/zhh/mapper/Account.xml"></mapper>
</mappers>

調用MyBatis原生接口來執行操作

public class MybatisTest {
    /**
     * 入門案例
     * @param args
     */
    public static void main(String[] args) throws IOException {
        // 1.讀取配置文件
        InputStream in= Resources.getResourceAsStream("Config.xml");
        // 2.創建SqlSessionFactory
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        SqlSessionFactory factory=builder.build(in);
        // 3.使用工廠生產SqlSession對象
        SqlSession session=factory.openSession();
        String statement="com.zhh.mapper.AccoutMapper.save";
        Account account=new Account(1L,"張三",12);
        session.insert(statement,account);
        // 4.釋放資源
         session.commit();
    }
}

使用Mapper代理實現自定義接口(推薦)

  • 自定義接口,定義相關業務方法
  • 編寫與方法相對應的Mapper.xml

1.自定義接口

package com.zhh.repository;
import com.zhh.entity.Acount;
import java.util.List;

public interface AccountRepository{
    public int save(Account account);
    public int update(Account account);
    public int deleteById(long id);
    public List<Account> findAll(); 
    public Account findById(long id);
}

2.創建接口對應的Mapper.xml,定義接口方法對應的SQL語句。statement標籤會根據SQL執行的業務選擇。MyBatis框架會根據規則自動創建接口實現類的代理對象。(後面的代碼用了自己的例子)

規則:

  • Mapper.xml中namespace爲接口的全類名。
  • Mapper.xml中statement的id爲接口中對應的方法名
  • Mapper.xml中statement的parameterType和接口對應方法的參數類型一致
  • Mapper.xml中statement的resultType和接口中對應方法的返回值類型一致
<?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:命名空間,用於隔離sql,還有一個很重要的作用,後面會講 -->
<mapper namespace="com.iweb.dao.IUserDao">
    <!-- id:statement的id 或者叫做sql的id-->
    <!-- parameterType:聲明輸入參數的類型 -->
    <!-- resultType:聲明輸出結果的類型,應該填寫pojo的全路徑 -->
    <!-- #{}:輸入參數的佔位符,相當於jdbc的? -->

    <!-- 通過id查詢一個用戶 -->
    <select id="findAll" resultType="com.iweb.domain.User">
		select * from user;
	</select>
    <select id="findById" parameterType="long" resultType="com.iweb.domain.User">
        select * from user where id=#{id};
    </select>
    <insert id="save"  parameterType="com.iweb.domain.User" >
        insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address});
    </insert>

    <update id="update" parameterType="com.iweb.domain.User">
        update user set id=#{id},username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#
        {id};
    </update>
    <delete id="deleteById" parameterType="long">
        delete from user where id=#{id};
    </delete>

</mapper>

3.在config.xml中註冊

<mappers>
        <!--        <mapper class="com.xl.dao.AccountDao"/>-->
        <mapper resource="com/iweb/dao/IUserDao.xml"></mapper>
        <package name="com.xl.dao"/>
    </mappers>

4.調用接口的代理對象完成相關的業務操作

public class MybatisTest {
    /**
     * 入門案例
     * @param args
     */
    public static void main(String[] args) throws IOException {
        // 1.讀取配置文件
        InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2.創建SqlSessionFactory
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        SqlSessionFactory factory=builder.build(in);
        // 3.使用工廠生產SqlSession對象
        SqlSession session=factory.openSession();
        // 4.使用SqlSession創建Dao接口的代理對象
        IUserDao userDao=session.getMapper(IUserDao.class);
        // 5.使用代理對象執行方法
        //添加
        User user1=new User(6,"張華", Date.valueOf("1997-11-27"),"男","安徽");
        userDao.save(user1);
        session.commit();
        //查找全部
        List<User> users=userDao.findAll();
        for(User user:users){
        System.out.println(user);
        }
        //按Id查找
        User user2=userDao.findById(1L);
        System.out.println(user2);
        //更新數據
        user2.setId(1L);
        user2.setUsername("大華");
        user2.setBirthday(Date.valueOf("1997-11-27"));
        user2.setSex("男");
        user2.setAddress("安徽");
        int result=userDao.update(user2);
        //刪除數據
        int result=userDao.deleteById(4L);
        System.out.println("result");
        session.commit();
        // 6.釋放資源
        session.close();
        session.close();
    }
}

Mapper.xml

  • statement標籤:select、update、delete、insert分別對應查改刪增

  • parameterType:參數數據類型

    1.基本數據類型,通過id查詢Account

    <select id="findById" parameterType="long" resultType="com.zhh.entity.Account">
    select * from t_account where id=#{id};
    </select>
    

    2.String類型,通過name查詢Account

    <select id="findName" parameterType="java.lang.String" resultType="com.zhh.entity.Account">
    select * from t_account where username=#{username};
    </select>
    

    3.包裝類,通過id查詢Account

    <select id="findById" parameterType="java.lang.Long" resultType="com.zhh.entity.Account">
    select * from t_account where id=#{id};
    </select>
    

    4.多個參數,通過username和age查詢Account

    param也可以用arg代替

    <select id="findByNameAndAge"
            resultType="com.zhh.entity.Account">
    select * from t_account where username=#{param1} and age=#{param2};
    </select>
    

    5.Java Bean

    <update id="update" parameterType="com.iweb.domain.User">
    update user set id=#{id},username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id};
    </update>
    
  • resultType:結果類型

    1.基本數據類型,統計Account總數

    <select id="count"  resultType="int">
    select count(id) from t_account;
    </select>
    

    2.包裝類,統計Account總數

    <select id="findById"  resultType="com.zhh.entity.Integer">
    select count(id) from t_account;
    </select>
    

    3.String類型,通過id查詢Account的name

    <select id="findNameById"  resultType="java.lang.String">
    select username from t_account where id=#{id};
    </select>
    

    4.JavaBean類型

    <select id="findById" parameterType="long" resultType="com.iweb.domain.User">
    select * from user where id=#{id};
    </select>
    
  • 級聯查詢

    1.一對多

    Student

    @Data
    public class Student{
        private long id;
        private String name;
        private Classes classes;
    }
    

    Classes

    @Data
    public class Classes{
        private long id;
        private String name;
        private List<Student> students;
    }
    

    StudentRepository

    public interface StudentRepository{
    public Student findById(long id);
    }
    

    StudentRepository.xml

    <resultMap id="studentMap" type="com.zhh.entity.Student">
       <id colmumn="id" property="id"></id>
       <result column="name" property="name"></result>
       <association property="classes" javaType="com.zhh.entity.Classes">
        <id column="cid" property="id"></id>
        <result column="cname" property="name"></result>
        </association>
    </resultMap>
    <select id="findById"  parameterType="long" resultMap="studentMap">
    select s.id,s.name,c.id as cid,c.name as cname from student s ,classes c where s.id=#{id} and s.cid=c.id;
    </select>
    

    ClassesRepository.xml

    <resultMap id="classesMap" type="com.zhh.entity.Classes">
       <id colmumn="cid" property="id"></id>
       <result column="cname" property="name"></result>
       <collection property="students" ofType="com.zhh.entity.Student">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        </collection>
    </resultMap>
    

    !!!實體類中如果一個學生對應一個班級,一個對象就用

    是個集合就用

    2.多對多

    Customer

    @Data
    public class Customer{
        private long id;
        private String name;
        private List<Goods> goods;
    }
    

    Goods

    @Data
    public class Goods{
        private long id;
        private String name;
        private List<Customer> customer;
    }
    

    CustomerRepository

    public interface CustomerRepository{
        public Customer findById(long id);
    }
    

    GoodsRepository

    public interface GoodsRepository{
        public Goods findById(long id);
    }
    

    CustomerRepository.xml

    <resultMap id="customerMap" type="com.zhh.entity.Customer">
       <id colmumn="cid" property="id"></id>
       <result column="cname" property="name"></result>
    <collection property="goods" ofType="com.zhh.entity.Goods">
        <id column="gid" property="id"></id>
        <result column="gname" property="name"></result>
        </collection>
    </resultMap>
    <select id="findById"  parameterType="long" resultMap="customerMap">
    select c.id cid,c.name cname,g.id gid,g.name gname from customer c ,goods g,customer_goods cg where c.id=#{id} and cg.cid=c.id and cg.gid=g.id;
    </select>
    

    GoodsRepository.xml

    <resultMap id="goodsMap" type="com.zhh.entity.Goods">
       <id colmumn="gid" property="id"></id>
       <result column="gname" property="name"></result>
    <collection property="customers" ofType="com.zhh.entity.customer">
        <id column="cid" property="id"></id>
        <result column="cname" property="name"></result>
        </collection>
    </resultMap>
    <select id="findById"  parameterType="long" resultMap="goodsMap">
    select c.id cid,c.name cname,g.id gid,g.name gname from customer c ,goods g,customer_goods cg where g.id=#{id} and cg.cid=c.id and cg.gid=g.id;
    </select>
    

逆向工程

MyBatis框架需要:實體類、自定義Mapper接口、Mapper.xml

傳統的開發中上述的三個組件需要開發者手動創建,逆向工程可以幫助開發者自動創建三個組件,減輕開發者的工作量,提高工作效率。

如何使用

MyBatis Generator,簡稱MBG,是一個專門爲MyBatis框架開發者定製的代碼生成器,可自動生成MyBatis框架所有的實體類、Mapper接口、Mapper.xml,支持基本的CRUD操作,但是一些複雜的SQL需要開發者自己來完成。

  • 新建Maven工程,pom.xml

     <dependencies>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-core</artifactId>
                <version>1.3.2</version>
            </dependency>
    
        </dependencies>
    
  • 創建MBG配置文件generatorConfig.xml(可自定義名字)

    1.jdbcConnection配置數據庫連接信息

    2.javaModelGenerator配置JavaBean的生成策略

    3.sqlMapGenerator配置SQL映射文件策略

    4.javaClientGenerator配置Mapper接口的生成策略

    5.table配置目標數據表(tableName:表名,domainObjectName:javaBean類名)

    <?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="testTables" targetRuntime="MyBatis3">
            <jdbcConnection
                    driverClass="com.mysql.jdbc.Driver"
                    connectionURL="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8"
                    userId="root"
                    password="123456"
            >
            </jdbcConnection>
            <javaModelGenerator targetPackage="com.zhh.entity" targetProject="./src/main/java"></javaModelGenerator>
            <sqlMapGenerator targetPackage="com.zhh.repository" targetProject="./src/main/java"></sqlMapGenerator>
            <javaClientGenerator type="XMLMAPPER" targetPackage="com.zhh.repository" targetProject="./src/main/java"></javaClientGenerator>
            <table tableName="t_user" domainObjectName="User"></table>
        </context>
    </generatorConfiguration>
    
  • 創建Generator執行類

    public class Main {
        public static void main(String[] args) throws IOException, XMLParserException {
            List<String> warings=new ArrayList<String>();
            boolean overwrite=true;
            //配置文件
            String genCig="/generatorConfig.xml";
            File configFile=new File(Main.class.getResource(genCig).getFile());
            ConfigurationParser configurationParser=new ConfigurationParser(warings);
            Configuration configuration=null;
            try {
                configuration=configurationParser.parseConfiguration(configFile);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (XMLParserException e) {
                e.printStackTrace();
            }
            DefaultShellCallback callback=new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator=null;
            try {
                myBatisGenerator =new MyBatisGenerator(configuration,callback,warings);
            } catch (InvalidConfigurationException e) {
                e.printStackTrace();
            }
            try {
                myBatisGenerator.generate(null);
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    

MyBatis延遲加載

  • 什麼是延遲加載?

    延遲加載也叫懶加載、惰性加載,使用延遲加載可以提高程序的運行效率,針對數據持久層的操作,在某些特定情況下去訪問特定的數據庫,在其他情況下不訪問某些表,從一定程度上減少了Java應用與數據庫的交互次數。

    查詢學生和班級的時,學生和班級是兩張不同的表,如果當前需求只需要獲取學生的信息,那麼查詢學生單表即可,如果需要通過學生獲取對應的班級信息,則必須查詢兩張表。

    不同的業務需求,需要查詢不同的表,根據具體的業務需求來動態減少數據表查詢

    public interface StudentRepository{
        public Student findByIdLazy(long id);
    }
    
    <resultMap id="studentMapLazy" type="com.zhh.entity.Student">
       <id colmumn="id" property="id"></id>
       <result column="name" property="name"></result>
       <association property="classes" javaType="com.zhh.entity.Classes"
    select="com.zhh.respository.ClassesRepository.findByIdLazy"   column="cid">
       </association>
    </resultMap>
    <select id="findByIdLazy"  parameterType="long" resultMap="studentMapLazy">
    select * from student where id=#{id};
    </select>
    
    public interface ClassesRepository{
        public Classes findByIdLazy(long id);
    }
    
    
    <select id="findByIdLazy"  parameterType="long" resultType="com.zhh.entity.Classes">
    select * from classes where id=#{id};
    </select>
    

nt">






select * from student where id=#{id};


```java
public interface ClassesRepository{
    public Classes findByIdLazy(long id);
}

<select id="findByIdLazy"  parameterType="long" resultType="com.zhh.entity.Classes">
select * from classes where id=#{id};
</select>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章