MyBatis入门
MyBatis入门
MyBatis简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBatis是半ORM映射框架,它需要在数据库里手动建表,CURD操作时要自己写SQL语句,而Hibernate是全ORM映射框架,它只需要配置好文件,表会自动生成,CURD的SQL语句也是自动生成的,这是他们的主要区别
中文文档
http://www.mybatis.org/mybatis-3/zh/index.html
10.1搭建MyBatis环境(使用MyBatis实现数据表的查询)
MyBatis快速入门
1.下载jar 包
Jar包下载路径
http://repo1.maven.org/maven2/org/mybatis/mybatis/
2.附加jar包
3.编写MyBatis配置文件 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 default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" /> <property name="username" value="hmy" /> <property name="password" value="hmy" /> </dataSource> </environment> </environments> <mappers> <mapper resource="cn/happy/entity/Dept.xml" /> </mappers> </configuration>
4.创建实体类Dept
package cn.happy.entity; public class Dept { private Integer deptNo; private String deptName; public Integer getDeptNo() { return deptNo; } public void setDeptNo(Integer deptNo) { this.deptNo = deptNo; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } }
6.创建SQL映射文件 Dept.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="cn.happy.entity.Dept"> <!-- 查询所有的部门 --> <select id="selectAllDept" resultType="cn.happy.entity.Dept"> select * from dept </select> <!-- 添加部门 --> <insert id="insertDept" parameterType="cn.happy.entity.Dept"> insert into dept values(stu_num.nextval,#{deptName}) </insert> <!-- 删除部门 --> <delete id="deleteDept" parameterType="cn.happy.entity.Dept"> delete from dept where deptno=#{deptNo} </delete> <!-- 修改部门 --> <update id="updateDept" parameterType="cn.happy.entity.Dept"> update dept set deptname=#{deptName} where deptno=#{deptNo} </update> <!-- 模糊查询部门 --> <select id="likeDept" parameterType="cn.happy.entity.Dept" resultType="cn.happy.entity.Dept" > select * from dept where deptname like '%${deptName}%' </select> </mapper>
6.书写测试类
package test; import java.io.IOException; import java.io.Reader; import java.util.List; 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.Before; import org.junit.Test; import cn.happy.entity.Dept; public class MyBatis { SqlSession session; @Before public void mybefore() throws IOException{ Reader reader=Resources.getResourceAsReader("MyBatis-configure.xml"); SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(reader); session = factory.openSession(); } /** * 模糊查询部门 * */ @Test public void likeDept(){ Dept dept=new Dept(); dept.setDeptName("物业"); List<Dept> list = session.selectList("likeDept", dept); for (Dept dept2 : list) { System.out.println(dept2); } session.close(); } /** * 修改部门 * */ @Test public void updateDept(){ Dept dept=new Dept(); dept.setDeptNo(1); dept.setDeptName("物业部"); int count = session.update("updateDept", dept); session.commit(); session.close(); System.out.println(count); } /** * 删除部门 * */ @Test public void deleteDept(){ Dept dept=new Dept(); dept.setDeptNo(5); int count = session.delete("deleteDept", dept); session.commit(); session.close(); System.out.println(count); } /** * 添加部门 * **/ @Test public void insertDept(){ Dept dept=new Dept(); dept.setDeptName("物业部"); int count = session.insert("insertDept", dept); session.commit(); session.close(); System.out.println(count); } /** * 查询部门 * */ @Test public void selectAllDept() throws IOException{ List<Dept> selectList = session.selectList("selectAllDept"); for (Dept dept : selectList) { System.out.println(dept.getDeptName()); } session.close(); } }
10.2使用MyBatis实现持久化操作
10.2.1使用MyBatis实现按条件查询
下面我们抛出一个问题,如果我们创建的实体类的属性名和数据库中对应表的列名不相同,我们是不是还只是做简单的查询。
答案是否定的,这样程序虽然不会报错,但我们发现查询出来的全是NULL
有一下两种解决方案:
package cn.happy.entity; public class Film { private Integer filmId; private String filmNames; private String actors; private String directors; private Double prices; private Integer typeId; public Integer getFilmId() { return filmId; } public void setFilmId(Integer filmId) { this.filmId = filmId; } public String getFilmNames() { return filmNames; } public void setFilmNames(String filmNames) { this.filmNames = filmNames; } public String getActors() { return actors; } public void setActors(String actors) { this.actors = actors; } public String getDirectors() { return directors; } public void setDirectors(String directors) { this.directors = directors; } public Double getPrices() { return prices; } public void setPrices(Double prices) { this.prices = prices; } public Integer getTypeId() { return typeId; } public void setTypeId(Integer typeId) { this.typeId = typeId; } }
对应的数据表
很显然对应名称不相同
我们未做任何避免措施时查询得到的结果
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <!--接口 --> 6 <mapper namespace="cn.happy.dao.Film"> 7 8 <!-- 查询所有的部门 --> 9 <select id="getAllfilms" resultType="Film"> 10 select * from film 11 </select> 12 13 </mapper>
测试类
1 package test; 2 3 import java.io.IOException; 4 import java.io.Reader; 5 import java.util.List; 6 7 import org.apache.ibatis.io.Resources; 8 import org.apache.ibatis.session.SqlSession; 9 import org.apache.ibatis.session.SqlSessionFactory; 10 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 import cn.happy.entity.Film; 15 16 public class FilmTest { 17 18 SqlSession session; 19 @Before 20 public void mybefore() throws IOException{ 21 Reader reader=Resources.getResourceAsReader("MyBatis-configure.xml"); 22 23 SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); 24 SqlSessionFactory factory = builder.build(reader); 25 session = factory.openSession(); 26 27 } 28 29 @Test 30 public void test(){ 31 List<Film> list = session.selectList("cn.happy.dao.Film.getAllfilms"); 32 for (Film film : list) { 33 System.out.println(film.getFilmNames()); 34 } 35 } 36 }
查询结果
方案一、使用as关键字,将数据库中表的列名as为实体类中的属性名
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <!--接口 --> 6 <mapper namespace="cn.happy.dao.Film"> 7 8 <!-- 查询所有的部门 --> 9 <select id="getAllfilms" resultType="Film"> 10 select filmName as filmNames,filmNo as filmId,price as prices ,actor as actors, director as directors,typeId from film 11 </select> 12 13 </mapper>
查询结果
方案二、使用resultMap进行解决
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <!--接口 --> 6 <mapper namespace="cn.happy.dao.Film"> 7 8 <resultMap type="Film" id="resultmapper"> 9 <id property="filmId" column="filmno"/> 10 <result property="filmNames" column="filmName"/> 11 <result property="actors" column="actor"/> 12 <result property="directors" column="director"/> 13 <result property="prices" column="Prices"/> 14 <result property="typeId" column="typeId"/> 15 </resultMap> 16 <!-- 查询所有的部门 --> 17 <select id="getAllfilms" resultMap="resultmapper"> 18 select * from film 19 </select> 20 21 </mapper>
测试结果
2.使用session.getMapper()方法实现
SqlSession提供了一个getMapper()方法获取到接口的具体实现类
MyBatis面向接口编程中,第二种方式DeptDao dept=session.getMapper(DeptDao.class);得到了一个DeptDao的代理类,代理类是通过JDK的动态代理实现的,只要定义接口及接口的方法,MyBatis就会动态生成实现DeptDao接口的代理,由代理解析XML,调用SQL,并将结果返回,使用接口编程需要注意:namespace需要定义为接口的全限定名,映射语句的id配置需要与接口中的方法名相同
第一步:创建接口对象 接口的方法名保持和下面配置文件中 的id名称相同
DeptDao.java
package cn.happy.dao; import java.util.List; import cn.happy.entity.Dept; import cn.happy.entity.Emp; public interface DeptDao { public void add(Emp emp); public void update(Emp emp); public void delete(Emp emp); public List<Dept> getAllDept(); }
DeptMapper.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="cn.happy.dao.DeptDao"> <!-- 查询所有的部门 --> <select id="getAllDept" resultType="Dept"> select * from dept </select> <!-- 添加部门 --> <insert id="add" parameterType="Dept"> insert into dept values(stu_num.nextval,#{deptName}) </insert> <!-- 删除部门 --> <delete id="delete" parameterType="Dept"> delete from dept where deptno=#{deptNo} </delete> <!-- 修改部门 --> <update id="update" parameterType="Dept"> update dept set deptname=#{deptName} where deptno=#{deptNo} </update> </mapper>
测试代码
SqlSession session; @Before public void mybefore() throws IOException{ Reader reader=Resources.getResourceAsReader("MyBatis-configure.xml"); SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(reader); session = factory.openSession(); } /** * getMapper的使用 * **/ @Test public void select(){ DeptDao mapper = session.getMapper(DeptDao.class); List<Dept> allDept = mapper.getAllDept(); for (Dept dept : allDept) { System.out.println(dept.getDeptName()); } }
3.使用resultMap实现结果映射
配置select映射时,返回类型可以用resultType,也可以使用resultMap。resultType是直接表示返回类型的,而resultMap是对外部ResultMap的引用,但是resultType与resultMap
不能同时存在。在MyBatis执行实际查询时,其查询出来的每一个属性都放在一个对应的Map中,其中键是属性名,值则是其对应的值。当提供的返回类型属性是resultType的时候,MyBatis会将Map中键值对取出赋给resultType所指定的对象的属性,所以其实MyBatis的每一个查询的返回类型都是ResultMap,只是当我们提供的返回类型属性是resultType时,MyBatis会自动把对应的值赋给resultType所指定对象的属性,这就是在SQL语句