学校的考试也考的差不多了,就剩一个单片机了。昨天下午开始学习MyBatis,到现在差不多一天的时间,一遍看视频,一遍跟着敲一遍,再写一下博客。三步走战略,感觉还挺不错的!学到了不少东西,下面是自己肝的博客,主要得配置一些东西,感觉还是把这些记录下来,以后也能用得到。
首先我们要会建立一个maven工程,不会的小伙伴可以参考我以前写的这篇文章:maven配置使用,这个后面还介绍了Tomcat7的配置,接下来的MyBatis学习并不会用到它,所以看到3.2就行了,能建一个maven工程就可以了。
这篇博客总结的主要内容如下:
了解软件的三层架构,并明白为什么要学习MyBatis框架 建立maven项目,从零开始一步一步把MyBatis环境搭起来,并完成一个简单的查询sql操作 完成查询之后,举一反三,完成一个简单的插入sql操作 MyBatis设置打印日志、一些工具类的介绍、用idea创建MyBatis的配置文件模板 使用MyBatis的动态代理机制简化编程 MyBatis的sql传参 传参时 $ 和 # 的区别当然自己也就学了一天,所以也并没有多么深入,后续会继续写,小伙伴如果有问题或者发现有什么不对的地方,欢迎与我进行联系。昨天也注册了自己的微信公众号——【高松Sun】,欢迎关注交流!
我的本机mysql环境:springdb数据库内创建一个student表,里面有两组数据。
小伙伴们可以用自己的sql可视化工具创建这个表,并添加两条数据即可。
在src目录下,在默认的main文件夹下,添加java和resources两个文件夹,并分别将其标记为Sources Boot
和Resources Boot文件,在java文件夹中创建我们的包,如我的是cn.gs。
先把步骤贴上面,我们根据这几个步骤做就可以
1.mysql新建student表 2.加入maven的mybatis依赖,mysql驱动的依赖 3.创建实体类,Student--保存表中的一行数据 4.创建持久层的dao接口,定义操作数据库的方法 5.创建一个mybatis的配置文件 叫做sql映射文件:写sql语句的,一般一个表一个sql文件 这个文件是xml文件,文件名与接口文件名一样 6.创建mybatis的主配置文件 一个项目就是一个配置文件 主配置文件提供了数据库的连接信息和sql映射文件的位置信息 7.创建使用mybatis类 通过mybatis来访问数据库mysql中插入学生表,已完成
maven的pom.xml配置文件中,依赖项中加入mybatis和mysql驱动包,并在编译build里面加入扫描到.xml的配置。pom.xml文件如下
可能直接用这上面的依赖项的版本会提示找不到,小伙伴们要根据直接的maven仓库自己去选择自己有的
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.gs</groupId> <artifactId>mybatis-blog-test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>mybatis-blog-test Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.26</version> <scope>compile</scope> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> </dependencies> <build> <!--配置能编译.xml文件--> <resources> <resource> <directory>src/main/java</directory><!--所在的目录--> <includes><!--包括目录下的.properties,.xml 文件都会扫描到--> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build> </project> 在cn.gs下创建一个domain包,包下面创建一个Student类 public class Student { private Integer id; private String name; private String email; private Integer age; //再生成它的 toString 和 getter/setter方法 } 在cn.gs下创建一个dao包,包下面创建一个StudentDao接口 public interface StudentDao { //查询student表所有数据 public List<Student> selectStudents(); }创建mybatis的配置文件,叫做sql映射文件,文件名与接口文件名一样
即在dao包下创建StudentDao.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.gs.dao.StudentDao"> <select id="selectStudents" resultType="cn.gs.domain.Student"> select id,name,email,age from Student order by id </select> </mapper> <!--namespace: 唯一值,要求你使用dao接口的全限定名称--> <!--select 表示执行查询,也可用其他,如update、delete、insert等--> <!--id: 执行sql的唯一标识,要求你使用接口中定义的方法名称--> <!--resultType:表示返会结果的类型,如我们查询得到的就是Student类,写全限定名称--> 在resources目录下创建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> <!--环境配置 : 数据库连接信息--> <environments default="mydev"> <!-- id: 一个唯一值,自定义,表示环境名称--> <environment id="mydev"> <!-- transactionManager: mybatis的事物类型 type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事物处理)--> <transactionManager type="JDBC"/> <!-- dataSource: 表示数据源,连接数据库--> <dataSource type="POOLED"> <!--数据库的驱动类名--> <property name="driver" value="com.mysql.jdbc.Driver"/> <!--连接数据库的url字符串--> <property name="url" value="jdbc:mysql://localhost:3306/springdb"/> <!--mysql中我的用户名:root--> <property name="username" value="root"/> <!--root对应的登录密码:root--> <property name="password" value="root"/> </dataSource> </environment> <environment id="online"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/springdb"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!--sql映射文件--> <mappers> <mapper resource="cn/gs/dao/StudentDao.xml"/> </mappers> </configuration> 在cn.gs下面创建一个APP类,完成测试 public class App { public static void main( String[] args ) throws IOException { //访问mybatis读取Student数据 //1.定义mybatis主配置文件的名称,从类路径的跟开始(target/classes) String config = "mybatis.xml"; //2.读取这个config文件 InputStream is = Resources.getResourceAsStream(config); //3.创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //4.创建SqlSessionFactory对象 SqlSessionFactory factory = builder.build(is); //5.【重要】获取SqlSession对象,从SqlSessionFactory中获取 SqlSession sqlSession = factory.openSession(); //6.指定要执行的sql语句的表示,sql映射文件中的namesapce+ "." +标签的id值 String sqlId = "cn.gs.dao.StudentDao" + "." + "selectStudents"; //7.执行sql语句 List<Student> list = sqlSession.selectList(sqlId); list.forEach(stu -> System.out.println(stu)); //8.关闭SqlSession对象 sqlSession.close(); } }这样我们的MyBatis就快速入门了,这个过程确实会报不少错,但我们一定不要放弃,环境的配置虽然挺麻烦,但是如果这点问题都不去自己解决,那谈什么nb的技术岂不是天方夜谭了!加油!
前面我们学会了MyBatis的配置和简单使用,查询了sql的Student表数据,这次我们用它向Student表插入一条学生信息。
在StudentDao类中新添加一条方法:public int insertStudent(Student student);
在StudentDao.xml配置文件的mapper中新添加一条insert项
<insert id="insertStudent"> insert into student values(#{id},#{name},#{email},#{age}) </insert>括号中的 #{xx} 表示函数传的参数student的对应值,就是这样的写法,会用即可。
在测试文件中,要把将要执行的sql语句的表示修改一下,再用SqlSession的insertStudent方法执行,最后还要设置一下提交事务操作。
String sqlId = "cn.gs.dao.StudentDao" + "." + "insertStudent";//插入方法 int num = sqlSession.insert(sqlId, student);//执行,返回改变的行数 sqlSession.commit();//提交事务在MyBatis的主配置文件mybatis.xml中的configuration内添加一个setting即可
<!--设置输出日志--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>在utils包下创建一个MyBatisUtil类,作为MyBatis的工具类,它会返回一个SqlSession对象
public class MyBatisUtil { static SqlSessionFactory factory = null; //使用静态代码块,只创建一个SqlSessionFactory类即可 static { String config = "mybatis.xml"; try { InputStream is = Resources.getResourceAsStream(config); factory = new SqlSessionFactoryBuilder().build(is); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession(){ SqlSession sqlSession = null; if(factory!=null){ sqlSession = factory.openSession(); } return sqlSession; } }测试类中创建一个方法,使用这个测试类,用的时候直接通过类名加方法名获取SqlSession对象,然后定义sql的ID标识字符串,将其装载在sqlSession对象里执行即可。
@Test public void MyBatisUtilUse(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); String sqlId = "cn.gs.dao.StudentDao" + "." + "selectStudents"; List<Student> list = sqlSession.selectList(sqlId); }File --> Settings --> Editor --> File and Code Templates --> file选项,点击 + 创建新的模板
Name填入 mybatis-config,Extension填入 xml,页面格式写入以下内容,点击OK即可
<?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> <!--设置输出日志--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--环境配置 : 数据库连接信息--> <environments default="mydev"> <!-- id: 一个唯一值,自定义,表示环境名称--> <environment id="mydev"> <!-- transactionManager: mybatis的事物类型 type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事物处理)--> <transactionManager type="JDBC"/> <!-- dataSource: 表示数据源,连接数据库--> <dataSource type="POOLED"> <!--数据库的驱动类名--> <property name="driver" value="com.mysql.jdbc.Driver"/> <!--连接数据库的url字符串--> <property name="url" value="jdbc:mysql://localhost:3306/springdb"/> <!--连接数据库的用户名--> <property name="username" value="root"/> <!--连接数据库的用户名密码--> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="cn/gs/dao/StudentDao.xml"/> </mappers> </configuration>File --> Settings --> Editor --> File and Code Templates --> file选项,点击 + 创建新的模板
Name填入 mybatis-mapper,Extension填入 xml,页面格式写入以下内容,点击OK即可
<?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.gs.dao.StudentDao"> <select id="selectStudents" resultType="cn.gs.domain.Student"> select id,name,email,age from Student order by id </select> </mapper>使用MyBatis的动态代理机制,使用SQLSession.getMapper(dao接口)
getMapper能获取dao接口对应的实现类对象,这样获取的dao类就能执行接口中相对应的方法了。
@Test public void MyBatisProxyTest(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); //调用dao的方,执行数据库的查询方法 List<Student> students = dao.selectStudents(); students.forEach(stu-> System.out.println(stu)); }如果要执行插入操作同样的道理,执行dao的insertStudent方法即可。
在StudentDao接口中添加方法
Student selectStudentById(Integer id);//根据id查询,返回Student对象在StudentDao.xml接口中添加对应的select
<select id="selectStudentById" resultType="cn.gs.domain.Student"> select id,name,email,age from Student where id = #{id} </select>测试
@Test public void selectByIdTest(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao mapper = sqlSession.getMapper(StudentDao.class); Student student = mapper.selectStudentById(1001); System.out.println(student); }在StudentDao接口中添加方法
//传递多个参数,命名参数,在形参定义的前面加入 @Param("自定义参数名称") List<Student> selectMultiParam(@Param("myname") String name, @Param("myage") Integer age);在StudentDao.xml接口中添加对应的select
<select id="selectMultiParam" resultType="cn.gs.domain.Student"> select id,name,email,age from Student where name = #{myname} or age = #{myage} </select>测试
@Test public void selectMultiTest(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao mapper = sqlSession.getMapper(StudentDao.class); List<Student> students = mapper.selectMultiParam("zhangsan", 22); System.out.println(students); }和上一个一样,我们传name和age两个参数来进行查询,我们可以把这两个参数封装为一个对象,然后直接用 #{xx} 来实现sql查询即可
// 在vo包下面创建一个QueryParam对象,封装name和age成员变量 public class QueryParam { private String paramName; private Integer paramAge; ....;//实现其getter/setter,toString()方法 }在StudentDao接口中添加方法
//用对象来传递多个参数 List<Student> selectMultiObject(QueryParam queryParam);在StudentDao.xml接口中添加对应的select
<select id="selectMultiObject" resultType="cn.gs.domain.Student"> select id,name,email,age from Student where name = #{paramName} or age = #{paramAge} </select>测试
@Test public void selectMultiObjectTest(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao mapper = sqlSession.getMapper(StudentDao.class); QueryParam queryParam = new QueryParam(); queryParam.setParamName("zhangsan"); queryParam.setParamAge(22); List<Student> students = mapper.selectMultiObject(queryParam); System.out.println(students); }当然我们也可以选择用原有的Student类来作为传参对象,它本来就有name和age成员变量,这样也是可以的!
在StudentDao接口中添加方法
//传递多个参数,按位置 List<Student> selectMultiPosition(String name,Integer age);在StudentDao.xml接口中添加对应的select
<select id="selectMultiPosition" resultType="cn.gs.domain.Student"> select id,name,email,age from Student where name = #{arg0} or age = #{arg1} </select>#{arg0} 和 #{arg0} 表示参数位置:第一个参数和第二个参数
测试
@Test public void selectMultiPositionTest(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao mapper = sqlSession.getMapper(StudentDao.class); List<Student> students = mapper.selectMultiPosition("zhangsan",22); System.out.println(students); }前面我们传参时候在StudentDao.xml中,用的都是 #{} ,进行参数传递,用 ${} 其实也可以,但是会有问题。
那么这两个东西有什么区别呢?我们先把上面传递一个简单的参数用${}来替换一下,看看有什么区别?
还是原来的三步,只不过换了一下名字,在把mapper文件中那条select中的 #{} 换成了 ${} 即可
在StudentDao接口中添加方法
//用${}传递一个参数 Student selectStudentBy$(@Param("id") Integer id);在StudentDao.xml接口中添加对应的select
<select id="selectStudentBy$" resultType="cn.gs.domain.Student"> select id,name,email,age from Student where id = ${id} </select>测试
@Test public void selectStudentByIdWith$Test(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao mapper = sqlSession.getMapper(StudentDao.class); Student student = mapper.selectStudentBy$(1001); System.out.println(student); }观察输出的结果,发现可以呀,没问题,还是能查询出张三同学。
但是其实打印的日志不太一样,我把两张图片放出来,我们且看一看。
直接上结论:
#{}:是以预编译的形式,将参数设置到sql语句中;能防止sql注入${}:取出的值直接拼装在sql语句中;会有安全问题(sql注入)在StudentDao接口中添加方法
List<Student> selectStudentsSortBy$(@Param("option")String option);在StudentDao.xml接口中添加对应的select
<select id="selectStudentsSortBy$" resultType="cn.gs.domain.Student"> select id,name,email,age from Student order by ${option} </select>测试
@Test public void selectStudentsSortBy$Test(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao mapper = sqlSession.getMapper(StudentDao.class); List<Student> students = mapper.selectStudentsSortBy$("name"); System.out.println(students); }