目录
一:环境配置
一句话总结:约定大于配置,这将会是一个惨痛的教训(不行,我就要创新,我就要自成一派,这真的就是勇士啊!赐酒,让前辈写框架。)
网上有有Mybatis的教程,总结起来就是下载maven,然后配好系统的环境变量(可以通过cmd命令行知道是否maven安装好,然后就是建一个本地仓库和在maven的.config的setting,.xml配好阿里云的镜像和使用本地仓库的地址)。
在这里给出经验:
第一,idea的版本如果是2019(正如我的),则会与maven的3.6以上版本不兼容,建议用3.6及其以下版本的maven,不然结果就是连依赖都下不了。(这问题卡了我一天,最终果断怀疑而解决)
第二:建议在新建maven工程时默认配置好新建工程所用的maven安装地址以及maven的本地仓库地址,并配置好自动下载依赖。这样会给你更好的使用体验。
第三:配置mybatis
附上我的工程文件目录
注意新建文件习惯:
<1:main.java下新建com.itcast.Mapper包(用于写接口)
<2在com.itcast.pojo下写实体对象(如user,生成其get和set方法)
<3然后在src.resources下创建directory:com/itcast/Mapper/sql映射文件(用于写sql映射文件,也就是如图的userMapper.xml与接口进行绑定,绑定的条件是它们在同一目录下)。
解释:创建directory就是把sql映射文件和接口放到一起,不要误以为它们是两个路径,它们就是同一个路径,maven编译后可以看到userMapper接口的字节码文件和userMapper.xml是放在一起的。
这样看起来就非常的清楚。
二:用Mapper代理实现CRUD(增删改查)
步骤:
<1 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放在同一目录下。
<2 设置SQL映射文件的namespace属性为Mapper接口全限定名
<3 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致。
<通过SqlSession的getMapper方法获取Mapper接口的代理对象,如userMapper,再通过代理对象的.方法名执行对于方法。sql映射文件中的对应sql语句如 select update delete等等就是我们原生JDBC中的statement。
在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>
<!-- 给实体类进行包扫描,就是相当于起了个别名,后面的sql映射文件的返回值类型都不需要带包名-->
<typeAliases>
<package name="com.itcast.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="061457"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载sql映射文件 使用mapper代理特别注意sql映射文件的路径-->
<!-- <mapper resource="com/itcast/Mapper/userMapper.xml"/>-->
<!-- 使用包扫描,加载包内的全部的sql映射文件-->
<package name="com.itcast.Mapper"/>
</mappers>
</configuration>
对mybatis-config.xml文件进行需要注意的地方:(正如我特别加的注释)
通过对实体类和对sql文件类进行包扫描,能极其方便地进行配置
对实体类进行包扫描:
<typeAliases>
<package name="com.itcast.pojo"/>
</typeAliases>
作用:这样sql映射文件的sql的返回的对象类型不需要使用全类名(包名+类名的形式),默认就是对象名,这一点在后面的userMapper.xml中可以看到。以及这个<typeAliases>的位置是固定的,就按图中它所在的位置的放,不然报错警告。
对sql映射文件进行包扫描:
<package name="com.itcast.Mapper"/>
作用:简单,快捷避免繁琐加载sql映射文件,直接将com/itcast/mapper下的所有sql映射文件全部加载,而不是用<mapper resource>标签一个个地写,那样多麻烦啊。
user实体类
package com.itcast.pojo;
public class user {
/**
* user参数
*/
private Integer id;
private String name;
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
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;
}
@Override
public String toString() {
return "user{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
userMapper.xml(sql映射文件)
<?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接口的全类名-->
<mapper namespace="com.itcast.Mapper.userMapper">
<insert id="add">
insert into myuser (name,id) values (#{name},#{id})
</insert>
<update id="updateone">
update myuser
SET name=#{name}
where id=#{id};
</update>
<delete id="deleteone">
delete from myuser where id = #{id};
</delete>
<!-- result Type包名+类名 起了别名后,默认为pojo包下的实体类名 如user-->
<select id="selectALL" resultType="user">
select * from myuser;
</select>
<!-- 根据id 查询单一一个-->
<select id="selectone" resultType="user">
select * from myuser
where
id = #{id};
</select>
<select id="selectinfo" resultType="user">
select *
from myuser
where 1=1
<if test="id!=null" >
and id=#{id}
</if>
<if test="name!=null">
and name=#{name}
</if>
</select>
</mapper>
在userMapper.xml中可以看到我参数的返回类型都是用的user类而不是用的全类名,这就是对实体类进行包扫描的好处,这里推荐一个插件Mybatis X ,用了可以快速找到sql映射文件中statement所对应接口的方法。
好处:容易看出是否sql的id与接口中的方面名写错,一对红蓝鸟出CP,嘿嘿,而且这插件是自动帮你生成statement(也就是userMapper里的select ,update ,insert标签等),你只需要写sql语句就行,还帮你自动把返回对象的全类名写好了。
userMapper接口:
package com.itcast.Mapper;
import com.itcast.pojo.user;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface userMapper {
// List <user> selectALL();
List<user> selectALL();
user selectone(int id);
void updateone(@Param("name")String name ,@Param("id") int id);
void deleteone(int id);
user selectinfo(@Param("name")String name,@Param("id")Integer id);//多参数查询
void add(user user);
}
我定义了三个属性name id address,但在我数据库中放的是name id 和 tel 。
目的就是为了理解sql查询返回对象的过程:在sql要求返回是对象的情况下,如果查询到数据库中对应字段相同则就自动封装对象的相应属性,若mysql中没有对应属性,则对象对应属性为null。
带多个参数的查询用了@param("属性名")参数类型 值 为的就是让mybatis能识别那个参数是那个。这里带多个参数的查询不在赘述,有很多种方式。
附上test案例
import com.itcast.Mapper.userMapper;
import com.itcast.pojo.user;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMybatis {
@Test
public void TestSelectALL() throws IOException {
//获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取SqlSession对象
SqlSession session = sqlSessionFactory.openSession(true);
//获取Mapper接口代理对象
userMapper userMapper = session.getMapper(userMapper.class);
//查询所有
// List<user> list= userMapper.selectALL();
// for (user user : list) {
// System.out.println(user.toString());
// }
// // 查询单个
// user myuser=userMapper.selectone(2);
// System.out.println(myuser.toString());
// 查询不完整信息
user temp=null;
temp= userMapper.selectinfo("王五",null);
System.out.println(temp.toString());
//更新数据
userMapper.updateone("喜羊羊",5);
//删除
// userMapper.deleteone(8);
// 插入新数据
// user temp2=new user();
// temp.setName("刘星");
// temp.setId(13);
//
// userMapper.add(temp2);
session.close();
}
}
注意:
sqlSessionFactory.openSession(true);
这句是自动开始了事务提交,如果不传参数就默认为false,你所做的任何数据库的操作(那些更改数据库结构的操作都将被回滚,也就是无效了),此时就得调用session.commit方法手动提交事务。