mybatis helloworld【vaynexiao】

    <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(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
 
INSERT INTO `user` VALUES ('1', 'tom', '11');
INSERT INTO `user` VALUES ('2', 'jack', '12');

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/数据库名?useUnicode=true&amp;characterEncoding=utf-8" />  
              <property name="username" value="账号" />  
              <property name="password" value="密码" />  
           </dataSource>  
       </environment>  
    </environments>  
    <mappers>  
	  <!-- package 注册包下面的所有Mapper接口 -->  
	  <!-- <package name="com.xxx.xxx.mapperinterface"/>  -->  
	  <!-- resource属性 注册单个相对于类路径的Mapper.xml文件 -->  
	  <!-- <mapper resource="com/xxx/mybatis/mapper/UserMapper.xml"/>   --> 
	  <!-- url属性 注册一个绝对路径的的Mapper.xml文件 -->  
	  <!--  <mapper url="file:///E:/UserMapper.xml"/>   --> 
	  <!-- class属性 注册一个Mapper接口,接口必须与mapper.xml文件名同名,且同路径下 -->  
	  <!-- <mapper class="com.xxx.xxx.mapperinterface.UserMapper"/>   --> 
    </mappers>
</configuration>

创建实体类User.java

public class User {
       private int id;
       private String name;
       private int age;
     //toString、全参构造、无参构造、set、get、toString全部省略。。。
}

创建session工具类

做一个util包,放工具类,以后直接调用静态方法获取Session

SqlSession session = MyBatisUtil.getSqlSession();

public class MyBatisUtil {  
    public static SqlSessionFactory getSqlSessionFactory() throws IOException{  
        String resource = "mybatis的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)默认自动提交  
    }  
}

另一种写法

public class MyBatisUtil {

    private static SqlSessionFactory factory;
    private static ThreadLocal<SqlSession> local=new ThreadLocal<>();
    
    static{
        try {
            factory=new SqlSessionFactoryBuilder()
                .build(
                    MyBatisUtil.class
                        .getClassLoader()
                            .getResourceAsStream("mybatis-config.xml")
                );
        } catch (Exception e) {
            throw new ExceptionInInitializerError("MyBatisUtil初始化失败"+e.getMessage());
        }
    }

    public static SqlSession getSession(){
        SqlSession session = local.get();
        if(session==null){
            session = factory.openSession();
            local.set(session);
        }
        return session;
    }

    public static void close(){
        SqlSession session = local.get();
        if(session!=null){
            session.close();
            local.remove();
        }
    }
}

共有三种方式

方法1:xml进行数据操作

方法2:在dao层用注解的方式

方法3:采取xml和dao层接口组合使用的方法。显然 ,后者更加简单。

方法1:只需要xml

(过时,只需要调用xml文件接收参数执行sql,可抽离出namespace作为statement变量)

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

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

    <update id="dropTable">  
        drop table tableName
    </update>

    <update id="truncate" >  
        truncate table tableName
    </update>
	
</mapper> 

如果报错提示说没有 mapper.xml 文件

现在 pom.xml 中 build 标签下添加固定代码

        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

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.xxx.xxx.mapper.userMapper.";//注意后面有一个点,为了和后面的mapper文件中的id连接

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

        
        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);
        session.commit(); 
        System.out.println("selectList:"+list);

        String statement6 = namespace+"drop";
        int update = session.update(statement6, "tableName");
        session.commit(); 
        System.out.println("update:"+update);

        String statement7 = namespace+"truncate";
        int update = session.update(statement7, "tableName");
        session.commit(); 
        System.out.println("update:"+update);
 
        session.close();//必须释放session
    }
}

 方式2:xml+interface

xml 写法不变,增加 interface,

扫描二维码关注公众号,回复: 10291166 查看本文章
(需要xml和interface,namespace要和接口全名相同,建议使用此种方式)
public interface UserDao {
    public List<User> selectUser() throws Exception;
}

 Test.java

        UserDao mapper = session.getMapper(UserDao.class);
        List<User> list = mapper.selectUser();

方式3:interface和anotation

(只需要interface,注解将sql写在方法上,当有注解时,默认使用方式三,但只适用简单sql)

1mapper包下(建议如此)新建同名接口

public interface UserDao { 

	//根据接口全类名找到同名namespace来对应mapper.xml的namespace
	//方法名也要和mapper文件中id对应mapper.xml的<select>的id
	@Insert (  "insert into pcmc_user(name, age) values(#{name}, #{age})"  )
	public int insertUser(User user) throws Exception;
	
	@Delete (  "delete from pcmc_user where id=#{id}"  )
	public int deleteUser(int id) throws Exception;
	
	@Update (  "update pcmc_user set name=#{name},age=#{age} where  id=#{id}"  )
	public int updateUser (User user,int id) throws Exception;
	
	@Select (  "select * from pcmc_user where id = #{id}"  )
	public User selectOneUser(int id) throws Exception;
	
	@Select (  "select * from pcmc_user"  )
	public List<User> selectAllUser() throws Exception;
	
}

2,注册接口文件

如果使用 resource属性注册xml文件,按住Ctrl会提示红色错误,但是其实不影响,注册仍然会成功

<mappers> 
        <!-- package 注册包下面的所有Mapper接口 -->
        <!-- <package name="com.xxx.xxx.mapperinterface"/>  -->

        <!-- resource属性 注册单个相对于类路径的Mapper.xml文件 -->
        <mapper resource="com/xxx/xxx/mapper/UserMapper.xml"/>

        <!-- url属性 注册一个绝对路径的的Mapper.xml文件 -->
        <!--  <mapper url="file:///E:/UserMapper.xml"/>   --> 

        <!-- class属性 注册一个Mapper接口,接口必须与mapper.xml文件名同名,且同路径下 -->
        <!-- <mapper class="com.xxx.xxx.interface.UserMapper"/>   -->
</mappers>

3,Test.java同方式2Test.java

SqlSession session = MyBatisUtil.getSqlSession();//得到一个session
//Unhandled Exception:java.io.IOException  是因为少了throws Exception或者try/catch
UserMapper userMapper = session.getMapper(UserMapper.class);
int num = userMapper.insertUser( new User(87,"Bob",30) );//insertUser等于方法名
session.commit();
List<User> list = userMapper.selectAllUser();
System.out.println(list);

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

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,  --这里表示使用自增,步长默认1
  `name` varchar(255) DEFAULT NULL,
  `age` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
/* 假设已存在的数据中字段id中的最大值为9,而创建表的时候AUTO_INCREMENT=12
则下次通过程序往表中insert数据,且没有指定字段id的值时,id将从12开始计算起,而不是10

这个功能有什么作用呢?比如有些数据原来是写死的,没有记录到数据库中,后来由于需求变化需要做成动态管理,需要保存到数据库中,
而原来有部分app_id已经被使用了,不能用于其它的,此时AUTO_INCREMENT就被派上用场了。
不使用指定的下次自增初始值的话,有可能新插入的数据与旧数据主键冲突,
所以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>
发布了49 篇原创文章 · 获赞 103 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/vayne_xiao/article/details/104859022