MyBatis学习

MyBatis快速入门

JDBC example

package test.mybatis;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC
{
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
    static final String DB_URL = "jdbc:mysql://localhost/EMP";

    //  Database credentials
    static final String USER = "username";
    static final String PASS = "password";

    public static void main(String[] args)
    {
        Connection conn = null;
        Statement stmt = null;
        
        try{
            //STEP 2: Register JDBC driver
            Class.forName("com.mysql.jdbc.Driver");

            //STEP 3: Open a connection
            System.out.println("Connecting to database...");
            conn = DriverManager.getConnection(DB_URL,USER,PASS);

            //STEP 4: Execute a query
            System.out.println("Creating statement...");
            stmt = conn.createStatement();
            String sql;
            sql = "SELECT id, first, last, age FROM Employees";
            ResultSet rs = stmt.executeQuery(sql);

            //STEP 5: Extract data from result set
            while(rs.next()){
               //Retrieve by column name
               int id  = rs.getInt("id");
               int age = rs.getInt("age");
               String first = rs.getString("first");
               String last = rs.getString("last");
            }
            //STEP 6: Clean-up environment
            rs.close();
            stmt.close();
            conn.close();
         }catch(SQLException se){
            //Handle errors for JDBC
            se.printStackTrace();
         }catch(Exception e){
            //Handle errors for Class.forName
            e.printStackTrace();
         }finally{
            //finally block used to close resources
            try{
               if(stmt!=null)
                  stmt.close();
            }catch(SQLException se2){
            }// nothing we can do
            try{
               if(conn!=null)
                  conn.close();
            }catch(SQLException se){
               se.printStackTrace();
            }
         }
    }
}
其中关键的class有:Connection, Statement, DriverManager, ResultSet

jdbc dbutils hibernatemybatis

对比jdbc, dbutils能够自动封装查询结果集,不用操作statement和resultSet。
Hibernate, 基本不用写SQL 可以面向对象操作数据库
MyBatis处于dbutils和hibernate之间。自己写SQL到xml文件或者注解中。对比dbutils,在插入数据时,dbutils需要传入各属性参数,而Mybatis只需要传入对象。

mybatis example 

public static void main(String[] args) throws IOException
{
        Reader reader = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sessionFactory.openSession();
        String statement = "test.mybatis.userMapper.getUser";
        User user = session.selectOne(statement, 1);
}
其中主要的class有:SqlSessionFactory SqlSessionFactoryBuilder SqlSession
conf.xml -- 配置数据库连接参数以及userMappers,Utils类中提供getSession方法,该方法读取conf.xml中的属性值,返回Session对象。
userMappers.xml -- 将该实体类Mapper.xml在conf.xml中注册。
实体类Mapper.xml中定义curd操作的sql以及结果集到对象的映射
简单对象映射用resultType, 复杂对象(需要在类属性和表的列之间映射)可以用resultMap。一对多的情况可以在resultMap中定义association.

MyBatisCRUD操作

// 在实体类Mapper.xml中配置Sql语句
<pre name="code" class="html"><mapper namespace="test.mybatis.simple.userMapper1">
    <select id="getUser" parameterType="int" resultType="User">
        select * from Users where id = #{id}
    </select>
    <insert id="addUser" parameterType="User">
        insert into Users (name, age) values (#{name}, #{age})
    </insert>

    <delete id="deleteUser" parameterType="int">
        delete from Users where id = #{id}
    </delete>
    
    <update id="updateUser" parameterType="User">
        update Users set name=#{name}, age=#{age} where id=#{id}
    </update>
    <select id="getAllUsers" resultType="User">
        select * from Users
    </select>
</mapper>
 
 

ResultMap 映射实体类属性与字段名

在实体类Mapper.xml中配置Sql到结果集的映射,解决字段名和实体类属性名不匹配。
<mapper namespace="test.mybatis.simple.orderMapper1">
    <!-- 重命名字段名方法 -->
    <select id="getOrder" parameterType="int" resultType="Order">
        select order_id id, order_no orderNo, order_price price from Orders where order_id = #{id}
    </select>

    <!-- resultMap映射方法 -->
    <select id="getOrder2" parameterType="int" resultMap="getOrderMap">
        select * from Orders where order_id = #{id}
    </select>
    
    <resultMap type="Order" id="getOrderMap">
        <id property="id" column="order_id"/>
        <result property="orderNo" column="order_no"/>
        <result property="price" column="order_price"/>
    </resultMap>
</mapper>
 
 

Association 一对一

在实体类Mapper.xml中配置Sql到结果集的映射,解决一对一关联表查询。

    <select id="getClass" parameterType="int" resultMap="getClassMap">
        select c.id c_id, c.name c_name, t.id t_id, t.name t_name from Class c, Teacher t where c.teacher_id=t.id and c.id = #{id}
    </select>
    <resultMap type="Class" id="getClassMap">
        <id property="id" column="c_id"/>
        <result property="name" column="c_name"/>
        <association property="teacher" column="teacher_id" javaType="Teacher">
            <id property="id" column="t_id"/>
        	<result property="name" column="t_name"/>
        </association>
    </resultMap>
 
  

Collection 一对多

在实体类Mapper.xml中配置Sql到结果集的映射,解决一对多关联表查询。

    <!--联表查询-->
    <select id="getClass" parameterType="int" resultMap="getClassMap">
        select c.id c_id, c.name c_name, t.id t_id, t.name t_name, s.id s_id, s.name s_name from Class c, Teacher t, Student s where c.teacher_id= t.id and c.id=s.class_id and c.id = #{id}
    </select>

    <resultMap type="Class" id="getClassMap">
        <id property="id" column="c_id"/>
        <result property="name" column="c_name"/>
        <association property="teacher" column="teacher_id" javaType="Teacher">
            <id property="id" column="t_id"/>
        	<result property="name" column="t_name"/>
        </association>
        <collection property="list" ofType="Student">
            <id property="id" column="s_id"/>
            <result property="name" column="s_name"/>
        </collection>
    </resultMap>
     
    <!--嵌套查询-->
    <select id="getClass" parameterType="int" resultMap="getClassMap">
        select c.id c_id, c.name c_name, c.teacher_id teacher_id from class c where c.id=#{id} 
    </select>

    <select id="getTeacher" parameterType="int" resultType="Teacher">
        select t.id id, t.name name from Teacher t where t.id=#{id} 
    </select>

    <select id="getStudent" parameterType="int" resultType="Student">
        select s.id id, s.name name from Student s where s.class_id=#{id} 
    </select>    

    <resultMap type="Class" id="getClassMap">
        <id property="id" column="c_id"/>
        <result property="name" column="c_name"/>
        <association property="teacher" column="teacher_id" select="getTeacher"></association>
        <collection property="list" column="c_id" select="getStudent"></collection>
    </resultMap>

动态SQL与模糊查询OGNL表达式

利用OGNL表达式构造动态sql语句

    <parameterMap type="ConditionUser" id="getConditionUserMap"></parameterMap>
    
    <select id="getUser" parameterType="ConditionUser" resultType="User">
        select * from Users u where
        
        <if test='name != "%null%"'>
             u.name like #{name} and 
        </if>

        u.age between #{mixAge} and #{maxAge}
    </select>

调用存储过程

新建存储过程

create OR REPLACE PROCEDURE  get_user_count (sex_id IN NUMBER, user_count out NUMBER)
as
begin
if sex_id=0 then
select count(*) into user_count from p_user where p_user.sex='女';
else
select count(*) into user_count from p_user where p_user.sex='男' ;
end if;
end get_user_count;

定义UserMapper.xml

    <parameterMap type="java.util.Map" id="getUserCountMap">
    	<parameter property="sex" mode="IN" jdbcType="INTEGER"/>
    	<parameter property="usercount" mode="OUT" jdbcType="INTEGER"/>
    </parameterMap>
    
    <select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE">
        call get_user_count(?,?)
    </select>

Test example

        SqlSession session = Utils.getSession();
        
        String querySql = "test.mybatis.procedure.userMapper.getUserCount";
        
        Map<String, Integer> parameterMap = new HashMap<>();
        parameterMap.put("sex", 1);
        parameterMap.put("usercount", -1);
        
        session.selectOne(querySql, parameterMap);
        System.out.println(parameterMap.get("usercount"));
        session.close();

缓存

在hibernate中,一级缓存是session级,二级缓存是sessionFactory级别。
Mybatis类似,在Mybatis中,
一级缓存:基于PerpetualCache的hashMap本地缓存,其存储作用域为Session,当Session flush或close之后,该Session中的所有Cache就将清空。
二级缓存与一级缓存机制相同,默认也是采用PerpetualCache的HashMap存储,不同在于其作用域为Mapper(Namespace),并可自定义存储源,如Ehcache.
对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存namespaces)的进行了C/U/D操作后,默认该作用域下所有select中的缓存将被clear。

A) UserMapper.xml

<mapper namespace="test.mybatis.cache.userMapper">
    <cache></cache> // 配置二级缓存
    <select id="getUser" parameterType="int" resultType="User">
        select * from users where id=#{id}
    </select>
    
    <select id="getAllUsers" resultType="User">
        select * from users
    </select>
    
    <update id="updateUser" parameterType="User">
        update users set name=#{name}, age=#{age} where id = #{id}
    </update>
</mapper>

B) Test example

    public static void main(String[] args) throws IOException
    {
        SqlSessionFactory factory = Utils.getSessionFactory();
        SqlSession session = factory.openSession();
                
        String querySql = "test.mybatis.cache.userMapper.getUser";
        
        // 测试一级缓存
        User user1 = session.selectOne(querySql, 3);
        System.out.println(user1);
        User user2 = session.selectOne(querySql, 3); //不执行sql
        System.out.println(user2);
        
        //session.close();
        //session.clearCache();  // close()或者clearCache()方法或者CRD操作能清除缓存
        String updateSql = "test.mybatis.cache.userMapper.updateUser";
        session.update(updateSql, new User(4, "test1", 16));
        session.commit();
        
        System.out.println("---------");
        User user3 = session.selectOne(querySql, 3); // 执行sql
        System.out.println(user3);
        
        session.close();
        System.out.println("---------------------------------------");
        
        // 测试二级缓存
        SqlSession session1 = factory.openSession();
        User user4 = session1.selectOne(querySql, 3); //不执行sql
        session1.commit();
        System.out.println(user4);
        session1.close();
}

Spring整合

spring配置beans.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
	http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.2.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
	
<!-- 1. 数据源 : DriverManagerDataSource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>

<!-- 2. mybatis 的SqlSession 的工厂: SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="test.mybatis.spring.bean"/>
</bean>

<!-- 3. mybatis 自动扫描加载Sql 映射文件 : MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="test.mybatis.spring.mapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

<!-- 4. 事务管理 : DataSourceTransactionManager -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 5. 使用声明式事务 -->
<tx:annotation-driven transaction-manager="txManager" />
</beans>

mapper.xml与接口

public interface EmployeeMapper
{
    void save(Employee employee);
    void update(Employee employee);
    void delete(int id);
    Employee findById(int id);
List<Employee> findAll();
}

<!-- namespace名字与接口全类名一致
     id与接口的某个方法名一致
 -->
<mapper namespace="test.mybatis.spring.mapper.EmployeeMapper">
    <cache></cache>

    <select id="findById" parameterType="int" resultType="Employee">
        select * from employee where id=#{id}
    </select>
    
    <select id="findAll" resultType="Employee">
        select * from employee
    </select>
    
    <update id="update" parameterType="Employee">
        update employee set name=#{name}, birthday=#{birthday}, salary=#{salary} where id = #{id}
    </update>
    
    <delete id="delete" parameterType="int">
        delete from employee where id=#{id}
    </delete>
    
    <insert id="save" parameterType="Employee">
        insert into employee (name, birthday, salary) values (#{name}, #{birthday}, #{salary})
    </insert>
</mapper>

测试类

@RunWith(SpringJUnit4ClassRunner.class) // 使用Spring的测试框架
@ContextConfiguration("/beans.xml") // 加载spring的配置文件
public class TestEmployee
{
    @Autowired
    private EmployeeMapper employeeMapper;
    
    @Test
    public void testAdd() {
        Employee employee = new Employee(-1, "tom", new Date(), 1234);
        employeeMapper.save(employee);
    }
    
    @Test
    public void testUpdate() {
        Employee employee = new Employee(6, "Tom", new Date(), 3000);
        employeeMapper.update(employee);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值