Markdown语法

120 阅读4分钟

HelloWorld

依赖

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>  <!-- 仅仅为测试而加 -->
            <version>4.12</version>
        </dependency>
    </dependencies>

表设计

create table `user` (
	`id` int ,
	`name` varchar ,
	`age` int 
); 
insert into `user` (`id`, `name`, `age`) values('1','林更新','18');

resource下mybatis-config.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>
    <!-- environments 配置多个environment,供切换 -->
    <environments default="development"> <!--default指定一个默认环境的id-->
        <environment id="development">
            <!-- type:处理事务方式, 大多数情况使用jdbc,另一种 managed:将事物交给其他组件托管,如spring-->
            <transactionManager type="JDBC" />
            <!-- 配置数据库连接类型
            POOLED:常用的简单的JDBC配置,使用了连接池
            UNPOOLED:不使用连接池,每次均需要打开和关闭数据连接,很消耗性能,相当于DriverManager.getConnection(url,username,password)
            JDNI:从tomcat中获取一个内置的数据库连接池
            -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/cpt" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
    <!-- package 注册包下面的所有Mapper接口 -->
	<!-- <package name="com.baidu.cpt.mapper"/>-->
    <!-- resource属性 注册单个相对于类路径的Mapper.xml文件 -->
        <mapper resource="com/baidu/cpt/mapper/UserMapper.xml"/>
    <!-- url属性 注册一个绝对路径的的Mapper.xml文件 -->
    <!--    <mapper url="file:///E:/UserMapper.xml"/>   -->
    <!-- class属性 注册一个Mapper接口,接口必须与mapper.xml文件名同名,且同路径下 -->
    <!--    <mapper class="com.baidu.cpt.mapper.userMapper"/>-->
    </mappers>
</configuration>

Entity包中User.java

public  class User {
    private  int  id;
    private String name;
    private  int  age;
    //toString、全参构造、set、get、toString 此处全部省略。。。实际开发必须有,不然代码报错
}

Util包中:MybatisUtil.java

public class MyBatisUtil {
    public static SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream is = Resources.getResourceAsStream(resource);//使用类加载器加载mybatis的配置文件
        //构建sqlSession的工厂 build方法还可以追一个参数,指定环境environment标签的id
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        return sqlSessionFactory;
    }
    public static SqlSession getSqlSession() throws IOException{
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        return sqlSessionFactory.openSession();//若是设置为opsenSession(true)默认自动提交事务,就不需要手动commit 
    }
}

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">
        
<mapper namespace="com.baidu.cpt.mapper.UserMapper">
<!-- namespace为mapper指定唯一的id,通常设置成包名+sql映射的文件名-->
<!-- 这里namespace不建议写xml文件全名,这种方式已过时,建议写接口全名,使用面向接口的优秀方式 -->

        <!--  parameterType指明查询时使用的参数类型。如果参数只有1个则用简单类型,参数为多个时可用Map集合或实体对象,占位符必须用对象的属性名;
        resultType表示查询结果将要封装成的实体类,也可以为对象类型、Map类型、基本类型 -->
    <select id="selectOneUser" resultType="com.baidu.cpt.Entity.User" parameterType="int">
        select * from user where id = #{id}
    </select>
         
    <!--    useGeneratedKeys  设置保存时返回主键,true 开启,自动封装到对象中对应的属性,默认是false -->
    <!--    keyProperty  指定对象的哪个属性的主键 -->
    <insert id="insertUser" parameterType="com.baidu.cpt.Entity.User" useGeneratedKeys="true" keyProperty="id">
        insert into user(name, age) values(#{name}, #{age})
    </insert>
         
    <delete id="deleteUser">
        delete from user where id=#{id}
    </delete>
         
    <update id="updateUser" parameterType="com.baidu.cpt.Entity.User" >
        update user set nam e= #{name},age = #{age} where id = #{id}
    </update>
         
    <select id="selectAllUser" resultType="com.baidu.cpt.Entity.User">
        select * from user
    </select>

</mapper>

test文件夹中Test.java

public class Test {
    public static void main(String[] args)  throws Exception{

        SqlSession session = MyBatisUtil.getSqlSession();//至此得到一个session
        //Unhandled Exception:java.io.IOException  是因为少了throws Exception或者try/catch
        //org.apache.ibatis.binding.BindingException: Type interface xxx is not known to the MapperRegistry
        //上面的错误时因为namespace和接口名不相同,必须改为相同
        String namespace = "com.baidu.cpt.mapper.UserMapper.";//注意后面有一个点,为了和后面的mapper文件中的id连接

        String statement4 = namespace+"selectOneUser";
        User user = session.selectOne(statement4,1);
        //selectOne sql中需要一个参数就传一个,这里查出来几个字段,都会按照实体类构造方法按顺序进行赋值
        System.out.println("selectOne:"+user);
 
        String statement1 = namespace+"insertUser";//映射sql的标识字符串
        int insert = session.insert(statement1,new User(10,"张三",18)); 
        //insert 这里为什么插入后id并不是指定的10,因为该namespace中sql语句中没有插入id字段,而建表时主键id是自动增长的。
        session.commit(); //默认增删改 必须手动提交提交事务
        System.out.println("insert:"+insert);

        String statement2 = namespace+"deleteUser";
        int delete = session.delete(statement2,2);
        session.commit(); //默认增删改 必须手动提交提交事务
        System.out.println("delete:"+delete);

        String statement3 = namespace+"updateUser";
        int update = session.update(statement3,new User(1,"林更新",18));
        session.commit(); //默认增删改 必须手动提交提交事务
        System.out.println("update:"+update);

        String statement5 = namespace+"selectAllUser";
        List<User> list = session.selectList(statement5);
        System.out.println("selectList:"+list);
 
        session.close();//必须释放session
    }
}

三种方式区别

1,xml

<!-- mybatis-config.xml 中注册:UserMapper.xml,使用命名空间来找到 select 标签 -->
<mappers>
	<package name="com.baidu.cpt.mapper"/>
</mappers>

2,xml + interface(推荐,且最流行)

// 1,xml不变
    
// 2,增加接口
public interface UserMapper {
    public List<User> selectAllUser();  // 方法名必须和mapper文件的select标签id一致,mapper代理要求名字保持一致
}

// 3,测试方法和纯xml方式也不同,使用反射,根据接口类, 而不是namespace
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> lists = userMapper.selectAllUser();
for (User u : lists ) {
	System.out.println(u);
}

// 4,不再是注册xml,而是注册接口
<mappers>
    <package name="com.baidu.cpt.mapper"/>
</mappers>

3,interface + anotation

只需要interface,不再需要userMapper.xml,注解将sql写在方法上,当有注解时,默认使用方式三,但只适用简单sql
    
注意要同名,因为如下:
	本质:反射机制实现
	底层:动态代理!
    
// 1,新建一个接口文件,调用的方法不再是select标签,而是注解中sql
public interface UserMapperNew {

    @Select (  "select * from user"  )
    public List<User> selectAllUserNew() throws Exception;
    
    @Insert(  "insert into user(name, age) values(#{name}, #{age})"  )
    public int insertUser(User user) throws Exception;

    @Delete(  "delete from user where id=#{id}"  )
    public int deleteUser(int id) throws Exception;

    @Update(  "update user set name=#{name},age=#{age} where  id=#{id}"  )
    public int updateUser (User user,int id) throws Exception;

    @Select(  "select * from user where id = #{id}"  )
    public User selectOneUser(int id) throws Exception;
    
}
// 2,测试方法,调接口的方法,方法名无需和select标签一致,因为使用的该方法的注解中的sql,与userMapper.xml文件无关。
UserMapperNew userMapper = session.getMapper(UserMapperNew.class);
List<User> lists = userMapper.selectAllUserNew();
for (User u : lists ) {
	System.out.println(u);
}

other

关于@Param()注解

  • 基本类型的参数或者String类型,需要加上,相当于给形参指定一个传入sql的固定名字,必须和sql中名字对应
  • 引用类型不需要加
  • 如果只有一个基本类型的话,可以忽略,但是建议大家都加上
  • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名

useGeneratedKeys="true"

<insert id="insertUser" parameterType="com.huawei.cpt.vo.User" useGeneratedKeys="true" keyProperty="id">
    insert into user (id,name,age) values(#{id},"Dandy","123456@a")
</insert>

User类的id为主键,这里useGeneratedKeys="true"表示需要使用自增这个功能,keyProperty="id"表示把自增值取到后存入参数对象的id属性中,用于sql中赋值,所以该实体类必须有该属性,且有setter方法;既然从表里取自增值,那么表必须设置为自增。

AUTO_INCREMENT

假设,id此时自增到了10,然后手动插入一条记录,id为15,继续使用程序插入数据,会使用当前自增值,此时是11还是15,答案是:15,自增值会自动取最大值。

selectKey

查出一个随机数,作为user实体类的id属性进行赋值,然后insert into中取到这个id值进行数据插入;

所以User类中必须有id属性,且有setter方法,resultType也必须和Userid类型对应;

selectKey也有注解,但注解适用简单sql,就不研究了。太low

<insert id="insertUser" parameterType="com.huawei.cpt.vo.User">
    <selectKey keyProperty="id" order="BEFORE" resultType="int">
        select CEILING(RAND()*10000)
    </selectKey>
    insert into user (id, name, age) values (#{id}, #{name}, #{age})
</insert>