ORM框架–Mybatis—需要程序员自己写SQL语句,需要掌握Java,和sql语句
–Hibernate—纯面向对象的,不需要程序员自己写SQL语句,完全使用操作对象,需要掌握Java
1.什么是Mybatis?
Mybatis—>OEM框架—>对JDBC进行封装,是数据持久层的框架,数据持久层的技术,与JDBC操作步骤类似,所以为了减少繁琐,对JDBC进行了封装
框架:简单,好用,易上手,对一些东西进行封装
MyBatis是一个简化和实现了 Java 数据持久化层(persistence layer)的开源框架,它抽象了大量的JDBC冗余代码,并提供了一个简单易用的API和数据库交互。
MyBatis的前身是iBATIS,iBATIS于2002年由ClintonBegin创建。MyBatis3是iBATIS的全新设计,支持注解和Mapper。
MyBatis流行的主要原因在于它的简单性和易使用性。在Java应用程序中,数据持久化层涉及到的工作有:将从数据库查询到的数据生成所需要的Java对象;将Java对象中的数据通SQL持久化到数据库中。
MyBatis通过抽象底层的JDBC代码,自动化SQL结果集产生Java对象、Java对象的数据持久化数据库中的过程使得对SQL的使用变得容易。
2.基本流程总结
1.建立配置文件,实现映射文件的路径
2.建立mapper映射文件,在SQLMapper映射配置文件中配置SQL语句
3.建立一个接口,配置文件的方法要关联到接口中,实现在映射接口中的方法与关系映射文件的sql对应
4.建立实现类,编写java代码完成插入操作
3.以下是博主的教师给的一些mybatis配置的详细内容
mybatis的核心包只有一个mybatis-3.x.0.jar
mybatis的两种文件:
1)mybatis的配置文件:mybatis-config.xml,其中包括数据库连接信息,类型别名等等
特点:名字一般是固定的,位置是src下面
2)mybatis的映射文件:XxxxxMapper.xml,这个xml文件中包括Xxxx类所对应的数据库表的各种增删改查sql语句
特点:名字一般为XxxxMapper.xml,Xxxx是对应类的名字
位置不固定,一般放到一个专门的package里面
接下来是
mybatis中的映射接口XxxxMapper.java(和XxxxMapper.xml中的sql语句进行映射)
最终实现类通过XxxxMapper接口的实现类对象来调用xml中的SQL语句
其中还写了一个
mybatis中的SqlSession接口和sqlSessionFactory接口,专门用来产生SqlSession对象
以下是博主今天完成的作业,建立了一个书籍管理,仅供参考
Book.java :
import java.util.Date;
public class Book {
//编号
private Integer id;
//书名
private String bookName;
//作者
private String author;
//发布日期
private Date publishDate;
//价格
private Double price;
public Book() {}
public Book(Integer id, String bookName, String author, Date publishDate, Double price) {
this.id = id;
this.bookName = bookName;
this.author = author;
this.publishDate = publishDate;
this.price = price;
}
public Book(String bookName, String author, Date publishDate, Double price) {
this.bookName = bookName;
this.author = author;
this.publishDate = publishDate;
this.price = price;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getPublishDate() {
return publishDate;
}
public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Book [id=" + id + ", bookName=" + bookName + ", author=" + author + ", publishDate=" + publishDate
+ ", price=" + price + "]";
}
}
BookMapper.xml :
<mapper namespace="com.briup.mappers.BookMapper">
<resultMap type="Book" id="BookResult">
<id property="id" column="id"/>
<result property="bookName" column="bookName"/>
<result property="author" column="author"/>
<result property="publishDate" column="publishDate"/>
<result property="price" column="price"/>
resultMap>
<insert id="insertBook" parameterType="Book">
insert into books
values (#{id},#{bookName},#{author},#{publishDate},#{price})
insert>
<delete id="deleteBook" parameterType="int">
delete from books
where id=#{id}
delete>
<select id="selectBookByname" parameterType="String" resultMap="BookResult">
select *
from books
where bookName=#{bookName}
select>
<select id="selectBookByid" parameterType="int" resultMap="BookResult">
select *
from books
where id=#{id}
select>
<select id="selectBook" resultMap="BookResult">
select *
from books
select>
<select id="selectBookname" resultType="String">
select bookName
from books
select>
<select id="selectBookcount" resultType="int">
select count(*)
from books
select>
<update id="updateBookByid" parameterType="Book">
update from books
set bookName=#{bookName},author=#{author},publishDate#{publishDate},price=#{price}
where id=#{id}
update>
<select id="selectBookn" resultType="String">
select bookName
from books
select>
<select id="selectBooka" resultType="Object">
select author
from books
select>
<select id="selectBooknaa" resultType="Book">
select bookName,author
from books
select>
mapper>
BookMapper.java :
package com.briup.mappers;
import java.util.List;
import com.briup.pojo.Book;
public interface BookMapper {
public void insertBook(Book book);
public void deleteBook(int id);
public Book selectBookByname(String name);
public Book selectBookByid(int id);
public List selectBook();
public List selectBookname();
public int selectBookcount();
public void updateBookByid(Book book);
public List selectBooknaa();
}
BookService.java :
package com.briup.test;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.briup.common.MyBatisSqlSessionFactory;
import com.briup.mappers.BookMapper;
import com.briup.pojo.Book;
/**
* 在BookMapper.java接口中定义方法
* 在BookService中调用BookMapper.java接口中方法
* 完成以下功能(注意参照笔记中的实例)
*/
//处理书籍相关信息的服务类
public class BookService {
//添加书籍
//书籍的名称不能重复
// @Test
public void addBook(Book book){
try {
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
// Book b = new Book(1, "罗密欧与朱丽叶", "莎士比亚", new Date(), 100.0);
mapper.insertBook(book);
session.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
//删除书籍
//id值不存在则不能删除
public void removeBook(Integer id){
try {
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
mapper.deleteBook(id);
} catch (Exception e) {
e.printStackTrace();
}
}
//查找书籍
//通过名字
public Book findBookByName(String bookName){
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
Book book = mapper.selectBookByname(bookName);
return book;
}
//查找书籍
//通过id
public Book findBookByName(Integer id){
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
Book book = mapper.selectBookByid(id);
return book;
}
//查找所有书籍
// @Test
public List findAllBooks(){
// try {
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
List list = mapper.selectBook();
// for(Book li:list){
// System.out.println(li);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
return list;
}
//查找所有书籍的名字
// @Test
public List findAllBooksName(){
// try {
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
List list = mapper.selectBookname();
// for(String li:list){
// System.out.println(li);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
return list;
}
//查找一共有多少本书籍
public int findCountOfBook(){
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
int count = mapper.selectBookcount();
return count;
}
//修改书籍
//通过id确定修改的是那本书
public void updateBook(Book book){
SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
BookMapper mapper = session.getMapper(BookMapper.class);
mapper.updateBookByid(book);
}
//查询所有书籍的名字和对应的作者
// @Test
public List
以下是工厂类的写法
MyBatisSqlSessionFactory.java
package com.briup.common;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisSqlSessionFactory {
private static SqlSessionFactory sqlSessionFactory;
public static SqlSessionFactory getSqlSessionFactory(){
if(sqlSessionFactory == null){
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e.getCause());
}
}
return sqlSessionFactory;
}
public static SqlSession openSession() {
return openSession(false);
}
//boolean参数是否要自动提交
//false设置手动提交
//true设置为自动提交
public static SqlSession openSession(boolean autoCommit) {
return getSqlSessionFactory().openSession(autoCommit);
}
}
以下是配置文件的写法
mybatis-config.xml :
<configuration>
<properties resource="db.properties">
<property name="name" value="test"/>
properties>
<settings>
<setting name="logPrefix" value="LOG4J:"/>
settings>
<typeAliases>
<package name="com.briup.pojo"/>
typeAliases>
<typeHandlers>
<typeHandler handler="com.briup.handler.PhoneTypeHandler"/>
typeHandlers>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${name}" />
<property name="password" value="${pwd}" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/briup/mappers/BookMapper.xml"/>
mappers>
configuration>
总的来说配置文件中的指定文件路径一定要和映射文件的路径对应
映射文件中的指定文件路径一定要和接口的路径对应
XML文件里的SQL语句的id一定要和接口的方法和测试类里mapper调用的方法三者对应
接口中方法名和配置文件中id值一致;方法参数类型和parameterType属性值一种;方法返回值类型和returnType属性值一致。
需要注意的是
keyProperty—类当中的属性
column—表当中的列
映射文件是不提供方法的返回值类型
映射文件是不关心方法的返回值类型
resultType定义的不是方法的返回值类型,它定义的是查询出的每一行数据要封装的对象类型是什么
用到的映射语句
select insert update delete
mapper mapper.xml的根节点
namespace 接口全限定名
resultType和resultMap
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap 的引用,是结果集映射,但是resultType跟resultMap不能同时存在。
resultType=”id”;l
parameterType 参数类型
自定义MyBatis日志
日志记录优先级由上到下顺序递减:
SLF4J
Apache Commons Logging
Log4j2
Log4j
JDK logging
org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useLog4J2Logging();
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging();
org.apache.ibatis.logging.LogFactory.useStdOutLogging();
如果想自定义MyBatis日志记录,你应该在调用任何其它方法之前调用以上的其中一个方法
4.结果集映射 ResultMaps
简单的结果集映射
"属性名" id="结果集映射名称">
<id property="studId" column="stud_id" />
<result property="name" column="name" />
<result property="email" column="email" />
<result property="phone" column="phone" />
对ResultMap进行拓展
可以进行继承
"属性名" id="结果集映射名称" extends="被继承的结果集映射名称">
<result property="address.addrId" column="addr_id" />
<result property="address.street" column="street" />
<result property="address.city" column="city" />
<result property="address.state" column="state" />
<result property="address.zip" column="zip" />
<result property="address.country" column="country" />
一对一映射
我把我的代码写到这供参考
<mapper namespace="com.briup.mappers.One2oneMapper">
<resultMap type="Address" id="AddressResult">
<id property="addrId" column="addr_id"/>
<result property="street" column="street"/>
<result property="city" column="city"/>
<result property="state" column="state"/>
<result property="zip" column="zip"/>
<result property="country" column="country"/>
resultMap>
<resultMap type="Student" id="StudentResult">
<id property="stuId" column="stud_id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="phone" column="phone"/>
<result property="dob" column="dob"/>
<association property="address" resultMap="AddressResult">association>
resultMap>
<select id="findAllStudents" resultMap="StudentResult">
select *
from students s,addresses a
where s.addr_id=a.addr_id(+)
select>
<resultMap type="Student" id="StudentWithAddressResult">
<id property="stuId" column="stud_id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="phone" column="phone"/>
<result property="dob" column="dob"/>
<association property="address" column="addr_id" select="findAddressById">association>
resultMap>
<select id="findAddressById" parameterType="int" resultMap="AddressResult">
select *
from addresses
where addr_id=#{id}
select>
<select id="findStudentById" parameterType="int" resultMap="StudentWithAddressResult">
select *
from students
where stud_id=#{id}
select>
<insert id="insertAddress" parameterType="Address">
<selectKey resultType="int" keyProperty="addrId" order="BEFORE">
select my_seq.nextval from dual
selectKey>
insert into addresses
values(#{addrId},#{street},#{city},#{state},#{zip},#{country})
insert>
<insert id="insertStudent" parameterType="Student">
<selectKey resultType="int" keyProperty="stuId" order="BEFORE">
select my_seq.nextval from dual
selectKey>
insert into students
values(#{stuId},#{name},#{email},#{phone},#{dob},#{address.addrId})
insert>
mapper>
多对多映射
<mapper namespace="com.briup.mappers.One2ManyMapper">
<resultMap type="Course" id="CourseResult">
<id property="courseId" column="course_Id"/>
<result property="name" column="cname"/>
<result property="description" column="description"/>
<result property="startDate" column="start_date"/>
<result property="endDate" column="end_date"/>
resultMap>
<resultMap type="Tutor" id="TutorResult">
<id property="tutorId" column="tutor_Id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="phone" column="phone"/>
<collection property="courses" resultMap="CourseResult"/>
resultMap>
<select id="findTutors" resultMap="TutorResult">
select c.course_id,c.name cname,c.description,c.start_date,c.end_date,t.tutor_id,t.name,t.email,t.phone
from tutors t left outer join courses c
on t.tutor_id=c.tutor_id
select>
mapper>
5.书写动态的SQL语句样例
<mapper namespace="com.briup.mappers.DynamicSqlMapper">
先创建了一个映射关系resultMap,方便之后的使用:
"Course" id="CourseResult">
<id property="courseId" column="course_Id"/>
<result property="name" column="name"/>
<result property="description" column="description"/>
<result property="startDate" column="start_date"/>
<result property="endDate" column="end_date"/>
条件,map参数表示用户输入的信息(讲师id,课程名字,结束时间,开始时间),可以看到where语句放的第一个条件是tutor_id,也就是说需要先在map参数中输入一个id值,再判断下面的if语句,的意思是如果courseName不为空,也就是说在map参数中又输入了一个courseName,所以才不为空,则会根据前面输入的id和后面输入的name来查找所有信息,语句有and连接,所有可以清楚的拼接出某条sql语句供使用,输入的参数不同sql语句也不同,达到动态效果。下面的startDate和endDate类似。
例:我可以在测试类中只输入一个map.put(“tutorId”,1);就可以查询,多输入map.put(“courseName”, “%Java%”);就可以达到拼接sql语句的目的来精确查询。后面我会把我的测试例子写出来
<select id="selectCourse_if" parameterType="map" resultMap="CourseResult">
select *
from courses
where tutor_id=#{tutorId}
<if test="courseName !=null">
and name like #{courseName}
if>
<if test="startDate !=null">
and start_date >= #{startDate}
if>
<if test="endDate !=null">
and end_date #{endDate}
if>
select>
条件,功能强大,即使不写id后面的也能加上并且会自动去除第一位的and/or语句,即与上面的if语句类似,加上了where,就没有必要必须写id之后再加其他条件,可以直接通过courseName(课程名称)或者startDate,endDate来查询。
<select id="selectCourse_where" parameterType="map" resultMap="CourseResult">
select * from courses
<where>
<if test="tutorId!=null">
tutor_id=#{tutorId}
if>
<if test="courseName !=null">
and name like #{courseName}
if>
<if test="startDate !=null">
and start_date >= #{startDate}
if>
<if test="endDate !=null">
and end_date #{endDate}
if>
where>
select>
条件,这条语句作用字面意思,选择一种方式来完成查询,意味着只选一种而不是像上面一个可以多个条件一起。
<select id="selectCourse_choose" parameterType="map" resultMap="CourseResult">
select * from courses
<when test="searchBy=='Tutor'">
where tutor_id=#{tutorId}
when>
<when test="searchBy=='cName'">
where name like #{courseName}
when>
where start_date >= sysdate
select>
条件,元素和元素类似,但是提供了在添加前缀/后缀或者移除前缀/后缀方面提供更大的灵活性。
prefix表示有一个if成立则插入where语句
suffix表示后缀,和prefix相反
suffixOverrides=”and”表示如果最后生成的sql语句多一个and,则自动去掉.
prefixOverrides的意思是处理前缀,和suffixOverrides相反
<select id="searchCourses" parameterType="map" resultMap="CourseResult">
select * from courses
"where" suffixOverrides="or | and">
<if test=" tutorId != null ">
tutor_id = #{tutorId} and
if>
<if test="courseName != null">
name like #{courseName} and
if>
select>
foreach循环,例如想在只输入某个id的情况下,查询出所有信息,并且查询出所有其他id的信息,foreach循环的作用就非常强大了,item中代表要输入的value值,collection中代表要输入的一个整体。
<select id="selectCourse_foreach" parameterType="map" resultMap="CourseResult">
select * from courses
<if test="tutorIds!=null">
<where>
<foreach item="values" collection="tutorIds">
or tutor_id=#{values}
foreach>
where>
if>
select>
这里提供了一个生成in字句的方式:
<select id="searchCoursesByTutors" parameterType="map" resultMap="CourseResult">
select * from courses
<if test="tutorIds!= null">
<where>
tutor_id in
<foreach item="Value" collection="tutorIds" open="(" separator="," close=")">
#{Value}
foreach>
where>
if>
select>
元素和元素类似,如果其内部条件判断有任何内容返回时,他会插入SET SQL 片段。
"updateCourse" parameterType="Course">
update courses
<set>
<if test="name != null">name=#{name},if>
<if test="description != null">description=#{description},if>
<if test="startDate != null">start_date=#{startDate},if>
<if test="endDate != null">end_date=#{endDate},if>
set>
where course_id=#{courseId}
mapper>
博主的测试接口:
public interface DynamicSqlMapper {
public List<Course> selectCourse_if(Map<String,Object> map);
public List<Course> selectCourse_where(Map<String,Object> map);
public List<Course> selectCourse_choose(Map<String,Object> map);
public List<Course> selectCourse_foreach(Map<String,Object> map);
}
测试类:
public class DynamicSqlTest {
@Test
public void test_selectCourse_if(){
SqlSession session = null;
try {
session = MyBatisSqlSessionFactory.openSession();
DynamicSqlMapper mapper = session.getMapper(DynamicSqlMapper.class);
Map<String,Object> map = new HashMap<String, Object>();
map.put("tutorId",1);
map.put("courseName", "%Java%");
List<Course> course = mapper.selectCourse_if(map);
for(Course c:course){
System.out.println(c);
}
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void selectCourse_where(){
SqlSession session = null;
try {
session = MyBatisSqlSessionFactory.openSession();
DynamicSqlMapper mapper = session.getMapper(DynamicSqlMapper.class);
Map<String,Object> map = new HashMap<String, Object>();
map.put("tutorId",2);
map.put("courseName", "%Java%");
List<Course> course = mapper.selectCourse_where(map);
for(Course c:course){
System.out.println(c);
}
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void selectCourse_choose(){
SqlSession session = null;
try {
session = MyBatisSqlSessionFactory.openSession();
DynamicSqlMapper mapper = session.getMapper(DynamicSqlMapper.class);
Map<String,Object> map = new HashMap<String, Object>();
map.put("searchBy", "Tutor");
map.put("tutorId",1);
//如果有第二句key值为searchBy则会执行第二句的 因为map集合里key值相同会覆盖values值
map.put("searchBy", 1);
map.put("courseName", "%Java%");
List<Course> course = mapper.selectCourse_choose(map);
for(Course c:course){
System.out.println(c);
}
}catch(Exception e){
e.printStackTrace();
}
}
@Test
public void selectCourse_foreach(){
SqlSession session = null;
try {
session = MyBatisSqlSessionFactory.openSession();
DynamicSqlMapper mapper = session.getMapper(DynamicSqlMapper.class);
Map<String,Object> map = new HashMap<String, Object>();
List<Integer> list = new ArrayList<Integer>();
list.add(1);
map.put("tutorIds", list);
List<Course> course = mapper.selectCourse_foreach(map);
for(Course c:course){
System.out.println(c);
}
}catch(Exception e){
e.printStackTrace();
}
}