public class Employee { private Integer id; private String lastName; private String email; private String gender; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Employee{" + "id=" + id + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + ", gender='" + gender + '\'' + '}'; } }
<?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> <!-- 1. mybatis使用properties标签引入外部properties配置文件内容 --> <properties></properties> <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_study?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="EmployeeMapper.xml"/> </mappers> </configuration>
<?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:名称空间;指定为接口的全类名 id:唯一标识 resultType:返回值类型 #{id}:从传递过来的参数中取出id值 --> <mapper namespace="com.wjl.mybatis.dao.EmployeeMapper"> <select id="getEmpById" resultType="com.wjl.mybatis.bean.Employee"> select id,last_name lastName,email,gender from tbl_employee where id = #{id} </select> </mapper>
public void test01() throws IOException { //1. 根据xml配置文件(全局配置文件)创建一个sqlSessionFactory对象 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 2. 获取SqlSeeion实例,能直接执行已经映射的SQL语句,一个sqlSession代表和数据库的一次会话 SqlSession sqlSession = sqlSessionFactory.openSession(); try{ // 变量1未xml文件执行的方法,变量2为传入的参数 Employee employee = sqlSession.selectOne("com.mybatis.EmployeeMapper.selectEmp",1); System.out.println(employee); }finally { sqlSession.close(); } }
// 定义接口类 public interface EmployeeMapper { public Employee getEmpById(Integer id); }
<?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 namespace="com.wjl.mybatis.dao.EmployeeMapper"> <!-- id为接口中对应的方法名 resultType:返回值类型 #{id}:从传递过来的参数中取出id值--> <select id="getEmpById" resultType="com.wjl.mybatis.bean.Employee"> select id,last_name lastName,email,gender from tbl_employee where id = #{id} </select> </mapper>
@Test public void test02() throws IOException { //1.获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 2. 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); try { // 3.获取接口的实现类对象 EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(employee); }finally { sqlSession.close(); } }
注释:SqlSession
SqlSession代表和数据库的一次对话,用完必须关闭
SqlSession和connection都是非线程安全.每次使用都应该去获取新的对象
mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象(将接口和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> <!-- 1. mybatis使用properties标签引入外部properties配置文件内容 resource:引入类路径下的资源 url:引入网络路径或者磁盘路径下的文件 --> <properties resource="dbconfig.properties"></properties> <!-- 2. settings 包含很多重要的设置 用来设置每一个设置项 --> <settings> <!--开启驼峰命名法,默认false --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <!-- 3. typeAliases别名处理器 别名不区分大小写,同时也可以使用@Alias注解在类上为其指定一个别名--> <typeAliases> <!--typeAlias:为某个java类型起别名 type:指定要起别名的类型全类名;默认类名就是类名小写;employee alia:别名 --> <!-- <typeAlias type="com.mybatis.bean.Employee" alias="emp"></typeAlias>--> <!--package:为某个包下的所有类批量起别名 name:指定包名(为当钱包以及下面所有后代的包每一个类都起一个默认别名) --> <package name="com.mybatis.bean"></package> <!--批量起别名情况下,使用@Alias注解为某个类型指定新的别名 --> </typeAliases> <!-- 4. plugins --> <!--5. environments ,mybatis可以配置多种环境,default指定使用哪种环境 每一个environment是一个具体的环境信息,通过id来选择环境 必须配置transactionManager:事务管理器(两种:JDBC,MANAGED),也可自定事务管理器,实现TransactionFactory type表示事务管理器的类型 dataSource:数据源(UNPOOLED|POOLED|JNDI) 可以自定义数据源,实现DataSourceFactory --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!-- 6.databaseIdProvider标签 支持多数据厂商 DB_VENDOR 作用就是得到数据库厂商的标识,mybatis就能根据数据库厂商标识执行不同的sql MySQL,Oracle,SQL Server ,xxxx 在Mapper文件中通过databaseid来指定数据 --> <databaseIdProvider type="DB_VENDOR"> <property name="MySQL" value="mysql"></property> <property name="Oracle" value="oracle"></property> </databaseIdProvider> <!-- 7. mappers标签 将sql映射注册到全局配置中 --> <mappers> <!--mapper :注册一个sql映射 resource:引用类路径下的sql映射文件 url:引用网络或者磁盘路径下的资源 class:引用(注册接口) 1.有sql映射文件,映射文件必须与接口同名.并且放到同一个目录下 2.没有sql文件,所有的sql都是利用注释写在接口上 --> <mapper resource="EmployeeMapper.xml"/> <!-- package 批量注册--> <package name="com.wjl.mybatis.dao"></package> </mappers> </configuration>
public Employee getEmpById(@Param("id") Integer id);
#{} 是以预编译的形式,将参数设置到sql中,防止sql注入
${}取出参数值直接拼装在sql语句中,会有安全问题
大多情况下,我们取参数的值都应该区使用#{}
简单的增加,返回值可以是int类型代表插入多少行,也可以是boolean代表插入成功失败
<insert id="addEmp" parameterType="com.mybatis.bean.Employee" > insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender}) </insert>
获取生成的主键id
<insert id="addEmp" parameterType="com.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender}) </insert>
<!--Orcale不支持自增,Orcale使用序列来模拟自增 --> <insert id="addEmp" databaseId="orcale"> <!--keyProperty:查出的主键值封装给javaBean的哪个属性 order="BEFORE" :当前sql在插入sql之前运行 resultType 查出的返回值类型 运行顺序: 先运行selelctKey查询id的属性,查出id值封装给javaBean的id属性 在运行插入的sql,就可以取出id的对应值 --> <selectKey keyProperty="id" order="BEFORE" resultType="integer"> select EMPLOYEES_SEQ.nextval from dual </selectKey> <!--插入的主键使用序列中拿到的 --> insert into tbl_employee(id,last_name,email,gender) values(#{id},#{lastName},#{email},#{gender}) <!-- order="AFTER" 方式 <selectKey keyProperty="id" order="AFTER" resultType="integer"> select EMPLOYEES_SEQ.currval from dual </selectKey> insert into tbl_employee(id,last_name,email,gender) values(EMPLOYEE_SEQ.nextval,#{lastName},#{email},#{gender}) --> </insert>
<update id="updateEmp"> update tbl_employee set last_name =#{lastName},email=#{email},gender=#{gender} where id = #{id} </update>
<select id="getEmpById" resultType="com.mybatis.bean.Employee"> select id,last_name,email,gender from tbl_employee where id = #{id} </select>
<resultMap id="myEmp" type="com.wjl.mybatis.bean.Employee"> <!--指定主键列的封装规则 id定义主键会有底层优化 column:指定哪一列 property:指定对应的javabean属性 --> <id column="id" property="id"></id> <result column="last_name" property="lastName"></result> <result column="email" property="email"></result> <result column="gender" property="gender"></result> <!-- 其他不指定的列会自动封装,我们只要写resultMap就把全部的映射规则全都写上--> </resultMap>
<!--resultMap :自定义结果集规则映射 --> <select id="getEmployeeById" resultMap="myEmp"> select * from tbl_employee where id = #{id} </select>
新建实体类Department
package com.wjl.mybatis.bean; import java.util.List; public class Department { private Integer id; private String departmentName; private List<Employee> emps; public List<Employee> getEmps() { return emps; } public void setEmps(List<Employee> emps) { this.emps = emps; } public Integer getId() { return id; } @Override public String toString() { return "Department{" + "id=" + id + ", departmentName='" + departmentName + '\'' + '}'; } public void setId(Integer id) { this.id = id; } public String getDepartmentName() { return departmentName; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } }
在Employee中增加Department属性
public class Employee { private Integer id; private String lastName; private String email; private String gender; public Department department; }
数据库中Employee增加Department id
查询与员工对应的部门和id
<!--查询员工对应的部门,通过sql直接查询出对应的部门的名称与id --> <!--public Employee geeEmployeeAndDept(Integer id); --> <select id="geeEmployeeAndDept" resultMap="myEmpPlus"> select e.id id , e.last_name last_name , e.gender gender ,e.d_id d_id ,d.id did ,d.dept_name dept_name from tbl_employee e,tbl_department d where e.d_id = d.id and e.id = #{id} </select>
<!--级联查询:级联属性封装结果集 --> <resultMap id="myEmpPlus" type="com.wjl.mybatis.bean.Employee"> <id column="id" property="id"></id> <result column="last_name" property="lastName"></result> <result column="email" property="email"></result> <result column="gender" property="gender"></result> <result column="did" property="department.id"></result> <result column="dept_name" property="department.departmentName"></result> </resultMap>
<!--使用association定义关联单个对象的封装规则 --> <resultMap id="myEmpPlus2" type="com.wjl.mybatis.bean.Employee"> <id column="id" property="id"></id> <result column="last_name" property="lastName"></result> <result column="email" property="email"></result> <result column="gender" property="gender"></result> <!-- association 用来指定可以联合的javaBean对象 property="department":指定哪个属性可以是联合的对象 javaType="" 指定这个属性对象的类型 --> <association property="department" javaType="com.wjl.mybatis.bean.Department"> <id column="did" property="id"></id> <result column="dept_name" property="departmentName"></result> </association> </resultMap>
<resultMap id="myEmpPlus3" type="com.wjl.mybatis.bean.Employee"> <id column="id" property="id"></id> <result column="last_name" property="lastName"></result> <result column="email" property="email"></result> <result column="gender" property="gender"></result> <!-- association 定义关联对象的封装规则 select: 表明当前属性是调用select方法查询出的结果 column : 指定将哪一列的值传给这个方法 流程:使用select指定的方法(闯入cloumn指定的这列参数的值)查出对象,封装给对象 --> <association property="department" select="com.wjl.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </resultMap>
<!-- 首先查询员工的详细信息--> <select id="getEmpByIdStep" resultMap="myEmpPlus4"> select * from tbl_employee where id = #{id} </select>
<!-- 根据查询出来的depid查询部门信息--> <select id="getDeptById" resultType="com.wjl.mybatis.bean.Department"> select id,dept_name departmentName from tbl_department where id = #{id} </select>
这样分段查询时会将sql一起执行,全部查询出来,但有时候我们不需要查询出部门信息,只有需要
的时候再进行查询,可以设置懒加载进行查询,全局懒加载开启后,可以在查询的 association 标签上设置fetchType=“lazy” (collection开启懒加载也是如此):表示使用延迟加载(需要全局开启懒加载)
<settings> <!-- 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。 --> <setting name="lazyLoadingEnabled" value="true"></setting> <!--当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载. --> <setting name="aggressiveLazyLoading" value="false"></setting> </settings>
情景二:查询部门时将所该部门下的员工查询出来
<select id="getDeptByIdPlus" resultMap="mydept"> select d.id did, d.dept_name dept_name,e.id eid,e.last_name last_name ,e.email email ,e.gender gender from tbl_department d left join tbl_employee e on d.id = e.d_id where d.id = #{id} </select>
<resultMap id="mydept" type="com.wjl.mybatis.bean.Department"> <id column="did" property="id"></id> <result column="dept_name" property="departmentName"></result> <!--定义关联的集合类型的属性封装规则 ofType:指定集合中的元素的类型 --> <collection property="emps" ofType="com.wjl.mybatis.bean.Employee"> <!--定义集合中元素的封装规则 --> <id column="eid" property="id"></id> <result column="last_name" property="lastName"></result> <result column="email" property="email"></result> <result column="gender" property="gender"></result> </collection> </resultMap>
<resultMap id="mydeptstep" type="com.wjl.mybatis.bean.Department"> <id column="id" property="id"></id> <result column="dept_name" property="departmentName"></result> <collection property="emps" select="com.wjl.mybatis.dao.EmployeeMapperPlus.getEmpsByDepid" column="id" fetchType="lazy" > </collection> </resultMap>
扩展:将多列的值传递过去
将多列的值封装map传递,column="{key=column1,key2=column2}"
fetchType=“lazy” :表示使用延迟加载(需要全局开启懒加载 -lazy:延迟加载 -eager :立即
<delete id="deleteEmpById"> delete from tbl_employee where id = #{id} </delete>