mybatis学习日志之总结
一、介绍mybatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。
MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。
二、写一个简单的demo
1.首先在工程下的lib中导入相应的jar包
2.先写一个bean的实体类
public class User {
private int id;
private String name;
private int age;
}
3.创建一个UserMapper.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">
<!-- namespace:表示名称空间。现在的目的是区分id的. -->
<mapper namespace="com.zhiyou100.xz.mapper.UserMapper">
<!-- 查询年龄在10~30之间的用户
1、查询条件不在实体类中。参数类型封装到map中。#{参数}===map的键
2、封装一个实体类。min max
如果在xml文件中出现了特殊字符?1.使用转义字符<:< 2.CDATA
-->
<select id="selectByAge" parameterType="map" resultType="com.zhiyou100.xz.bean.User">
<![CDATA[select * from users where age>=#{min} and age<=#{max}]]>
</select>
<!-- 查询所有 -->
<select id="selectAll" resultType="com.zhiyou100.xz.bean.User">
select * from users
</select>
<!-- 根据id查询用户。id:标识该标签。
parameterType:参数类型。可以写 也可以省略
resultType:返回结果的类型。
#{id}:类似于EL表达式。 解析id的值
-->
<select id="getUser" parameterType="int" resultType="com.zhiyou100.xz.bean.User">
select * from users where id=#{id}
</select>
<!-- $ Preparing:insert into users(name,age) values('吴立琪',18):完成sql拼接。Statement sql注入的缺陷
如果你传入的为列名或表名时可以使用$
# insert into users(name,age) values(?,?):防止sql的注入。PreparedStatement
useGeneratedKeys="true" 表示使用字段生成的key
keyProperyty:把生产的key赋值到哪个属性上。
-->
<insert id="addUser1" parameterType="com.zhiyou100.xz.bean.User" useGeneratedKeys="true" keyProperty="id">
insert into users(name,age) values(#{name},#{age})
</insert>
<!--
parameterType:表示user类的对象。
相当于方法:
public void addUser(User user){
user.getName();
user.getAge();
}
-->
<insert id="addUser" parameterType="com.zhiyou100.xz.bean.User">
insert into users(name,age) values(#{name},#{age})
</insert>
<delete id="deleteUser" parameterType="int">
delete from users where id=#{id}
</delete>
<update id="updateUser" parameterType="com.zhiyou100.xz.bean.User">
update users set name=#{name},age=#{age} where id=#{id}
</update>
</mapper>
4.配置conf.xml文件,并引入数据源db.properties
<?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>
<!-- 引入数据源文件 -->
<properties resource="db.properties"/>
<!-- 为实体类取别名 -->
<typeAliases>
<!-- <typeAlias type="com.zhiyou100.xz.bean.User" alias="u"/> -->
<!-- 以下方法以该包下的所有类的类名作为别名 -->
<package name="com.zhiyou100.xz.bean"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<!-- 习惯把数据源的信息放到一个属性文件中,后缀名为.properties -->
<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>
<!-- 把映射文件引入到配置文件中 -->
<mappers>
<mapper resource="com/zhiyou100/xz/mapper/UserMapper.xml"/>
</mappers>
</configuration>
#数据源的信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
5.在src下加入日志信息文件log4j.properties
log4j.properties,
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
6.测试运行
package com.test;
import java.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import com.zhiyou100.xz.bean.User;
class TestMybatis {
static SqlSession session=null;
final String str="com.zhiyou100.xz.mapper.UserMapper";
@BeforeAll
static void setUpBeforeClass() throws Exception {
//解析配置文件conf.xml
Reader reader=Resources.getResourceAsReader("conf.xml");
//获取SessionFactory对象
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
//获取Session对象,表示jdbc中connection,操作数据库的
session=sessionFactory.openSession();
}
@Test
void testSelectByAge() {
Map<String,Integer> map=new HashMap<String,Integer>();
map.put("min",10);
map.put("max",30);
List<User> list=session.selectList(str+".selectByAge",map);
System.out.println(list);
}
@Test
void testAll() {
List<User> list=session.selectList(str+".selectAll");
System.out.println(list);
}
@Test
void testId() {
User user=session.selectOne(str+".getUser", 1);
System.out.println(user);
}
@Test
void testAdd() {
User user=new User("张三",20);
session.insert(str+".addUser1", user);
int id=user.getId();//通过user对象中的getId()方法获取添加记录后返回自增列的值
System.out.println(id);
}
@Test
void testDelete() {
int row=session.delete(str+".deleteUser", 3);
System.out.println(row);
}
@Test
void testUpdate() {
int row=session.update(str+".updateUser", new User(4,"里斯",20));
System.out.println(row);
}
@AfterAll
static void tearDownAfterClass() throws Exception {
session.commit();//提交数据
}
}
三、优化mybatis
1.连接数据库的配置单独放在一个properties文件中,如以上2-4中
2.为实体类定义别名,简化sql映射xml文件中的引用
<!-- 为实体类取别名 -->
<typeAliases>
<!-- <typeAlias type="com.zhiyou100.xz.bean.User" alias="u"/> -->
<!-- 以下方法以该包下的所有类的类名作为别名 -->
<package name="com.zhiyou100.xz.bean"/>
</typeAliases>
3.可以在src下加入log4j的配置文件,打印日志信息,如以上的2-5中。
注意要先添加log4j-1.2.17.jar
四、接口与映射文件结合使用
1.创建一个接口,该接口要和映射文件匹配(接口名、接口中的方法)
public interface UserDao {
/**
* 根据id查询
* @param id
* @return
*/
public User getUser(int id);
/**
* 添加
* @param user
*/
public void addUser(User user);
/**
* 删除用户
* @param id
*/
public void deleteUser(int id);
/**
* 更新用户
* @param user
*/
public void updateUser(User user);
/**
* 查询年龄在min~max之间的用户
* @param min
* @param max
* @return
* @Param:表示告诉mybatis把该方法的参数封装成map时,键名叫什么
*/
public List<User> selectByAge(@Param("min") int min,@Param("max") int max);
//这里默认mybatis把参数封装到所谓的map中,以键值对0,10 1,30 或param1,10 paramm2,30存放,
//并未以min,max为键名,要用@Param指出键名叫什么
//第二种方法
//public List<User> selectByAge(Map<String,Integer> map); }
2.映射文件中
<?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:表示名称空间。这里的namespace一定要与接口所在的包以及接口的名字一样 -->
<mapper namespace="com.zhiyou100.xz.dao.UserDao">
<!-- 这里的id一定要与接口中方法的名字进行对照
-->
<select id="getUser" parameterType="int" resultType="com.zhiyou100.xz.bean.User">
select * from users where id=#{id}
</select>
<!--
parameterType:表示user类的对象。
相当于方法:
public void addUser(User user){
user.getName();
user.getAge();
}
-->
<insert id="addUser" parameterType="com.zhiyou100.xz.bean.User">
insert into users(name,age) values(#{name},#{age})
</insert>
<delete id="deleteUser" parameterType="int">
delete from users where id=#{id}
</delete>
<update id="updateUser" parameterType="com.zhiyou100.xz.bean.User">
update users set name=#{name},age=#{age} where id=#{id}
</update>
<select id="selectByAge" parameterType="map" resultType="com.zhiyou100.xz.bean.User">
<![CDATA[select * from users where age>=#{min} and age<=#{max}]]>
</select>
</mapper>
3.测试
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.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import com.zhiyou100.xz.bean.User;
import com.zhiyou100.xz.dao.UserDao; class TestMybatis {
static SqlSession session=null;
final String str="com.zhiyou100.xz.mapper.UserMapper";
static UserDao userDao;
@BeforeAll
static void setUpBeforeClass() throws Exception {
//解析配置文件conf.xml
Reader reader=Resources.getResourceAsReader("conf.xml");
//获取SessionFactory对象
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader); //获取Session对象,表示jdbc中connection,操作数据库的
session=sessionFactory.openSession();
//得到接口的实现类
userDao=session.getMapper(UserDao.class);//相当于创建一个Dao对象
} @Test
void testSelectByAge() {
List<User> list=userDao.selectByAge(10, 30);
System.out.println(list); }
@Test
void testId1() {
User user=userDao.getUser(1);
System.out.println(user); }
@Test
void testAdd() {
userDao.addUser(new User("孔子",2000));
}
@Test
void testDelete() {
userDao.deleteUser(5); }
@Test
void testUpdate() {
userDao.updateUser(new User(6,"孔子",20)); }
@AfterAll
static void tearDownAfterClass() throws Exception {
session.commit();//提交数据 事物管理:要么都执行,要么都不执行
} }
五、解决列名与属性名不一致的情况
1. 解决方案为为查询的字段起别名 要求别名与属性名一致。
<!-- 这里的id一定要与接口中方法的名字进行对照
-->
<select id="selectById" resultType="com.zhiyou100.xz.bean.Order">
select order_id id,order_no no,order_price price from orders where order_id=#{id}
</select>
2.使用resultMap标签来定义实体类与字段之间的对应关系
<!-- resultMap:引用resultMap标签 不能与resultType同时用 -->
<select id="selectById2" resultMap="myMap">
select * from orders where order_id=#{id}
</select> <!-- resultMap:写属性与字段的对应关系
type:表示哪个实体类与表的对应关系
-->
<resultMap type="com.zhiyou100.xz.bean.Order" id="myMap">
<!-- id:标签标识表中的主键与实体类的值属性对应关系 -->
<id column="order_id" property="id"/>
<result column="order_no" property="no"/>
<result column="order_price" property="price"/>
</resultMap>
六、关联查询
- 多对一或一对一,如一个老师多个班级,利用association标签
链表查询时
<!-- resultMap:引用resultMap标签 -->
<select id="selectById" resultMap="clazzMapper">
select * from class c,teacher t where c.teacher_id=t.t_id and c_id=#{cid}
</select> <!-- resultMap:写属性与字段的对应关系
type:表示哪个实体类与表的对应关系
-->
<resultMap type="com.zhiyou100.xz.bean.Clazz" id="clazzMapper">
<!-- id:标签标识表中的主键与实体类的值属性对应关系 -->
<id column="c_id" property="cid"/>
<result column="c_name" property="cname"/>
<result column="teacher_id" property="tid"/>
<!-- 该类中引入的一的一方的属性
property:属性名
javaType:该属性的Java类型
-->
<!-- 链表查询 -->
<association property="teacher" javaType="com.zhiyou100.xz.bean.Teacher">
<id column="t_id" property="tid"/>
<result column="t_name" property="tname"/>
</association>
</resultMap>
嵌套查询时
<!-- resultMap:写属性与字段的对应关系
type:表示哪个实体类与表的对应关系
-->
<resultMap type="com.zhiyou100.xz.bean.Clazz" id="clazzMapper">
<!-- id:标签标识表中的主键与实体类的值属性对应关系 -->
<id column="c_id" property="cid"/>
<result column="c_name" property="cname"/>
<result column="teacher_id" property="tid"/>
<!-- 该类中引入的一的一方的属性
property:属性名
javaType:该属性的Java类型
-->
<!-- column:外键列
select="com.zhiyou100.xz.dao.TeacherDao.selectByTeacherId"
当另建一个TeacherDao时引用的方式
--> <association property="teacher" javaType="com.zhiyou100.xz.bean.Teacher"
column="teacher_id" select="selectByTeacherId">
</association>
</resultMap>
<!-- 以下为嵌套语句 -->
<select id="selectById" resultMap="clazzMapper">
select * from class where c_id=#{cid}
</select> <select id="selectByTeacherId" resultType="com.zhiyou100.xz.bean.Teacher">
select t_id tid,t_name tname from teacher where t_id=#{tid}
</select>
- 一对多,如一个班级多个学生,利用collection标签
<!--引用resultMap标签 -->
<select id="getClazz" parameterType="int" resultMap="clazzMap">
select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id = #{id}
</select> <!--resultMap:写数学与字段的对应关系
type:表示哪个实体类与表的对应关系
-->
<resultMap type="com.zhiyou100.klb.bean.Clazz" id="clazzMap">
<!-- ID:表示表中的主键与实体类的属性的对应关系 -->
<id column="c_id" property="cid"/>
<result column="c_name" property="cname"/>
<result column="teacher_id" property="tid"/> <association property="teacher" javaType="com.zhiyou100.klb.bean.Teacher">
<id column="t_id" property="tid"/>
<result column="t_name" property="tname"/>
</association>
<!-- ofType:集合中泛型的类型 -->
<collection property="students" ofType="com.zhiyou100.klb.bean.Student">
<id column="s_id" property="sid"/>
<result column="s_name" property="sname"/>
<result column="class_id" property="cid"/>
</collection>
</resultMap>
七、动态sql语句
1.if语句
<select id="selectByWhere1" parameterType="int" resultType="com.zhiyou100.xz.bean.User">
select * from users
<if test="name!=null">
where name=#{name}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</select>
2.if+where 语句
<select id="selectByWhere2" resultType="com.zhiyou100.xz.bean.User">
select * from users
<where>
<if test="name!=null">
and name=#{name}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</where>
</select>
3. if+set 语句
<update id="updateUser" parameterType="com.zhiyou100.xz.bean.User">
update users
<set>
<if test="name!=null">
name=#{name},
</if>
<if test="sex!=null and sex!=''">
sex=#{sex},
</if>
<if test="age>0">
age=#{age}
</if>
</set>
where id=#{id}
</update>
4. choose(when,otherwise) 语句+模糊查询用concat
<!-- choose+where+otherwise -->
<select id="selectByWhere3" resultType="com.zhiyou100.xz.bean.User">
select * from users
<where>
<choose>
<when test="name!=null and name!=''">
name like concat('%',#{name},'%')
</when>
<when test="sex!=null and sex!=''">
sex=#{sex}
</when>
<otherwise>
age>=#{age}
</otherwise>
</choose>
</where>
</select>
5. trim 语句
<!-- trim 前缀 -->
<select id="selectByWhere2" resultType="com.zhiyou100.xz.bean.User">
select * from users
<trim prefix="where" prefixOverrides="and / or">
<if test="name!=null">
and name=#{name}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</trim>
</select>
<!-- trim 后缀 -->
<update id="updateUser" parameterType="com.zhiyou100.xz.bean.User">
update users
<!--
prefix:把trim中返回的字符串前添加一个set
prefixOverrides:覆盖trim中返回的字符串的前缀为and | or
suffix:把trim中返回的字符串后添加一个指定字符串
suffixOverrides:覆盖trim中返回的字符串的前缀
-->
<trim prefix="set" suffixOverrides=",">
<if test="name!=null">
name=#{name},
</if>
<if test="sex!=null and sex!=''">
sex=#{sex},
</if>
<if test="age>0">
age=#{age}
</if>
</trim>
where id=#{id}
</update>
6. SQL 片段
<!-- sql片段 -->
<sql id="usercolumns">
id,name,age,sex
</sql> <select id="selectByWhere1" parameterType="int" resultType="com.zhiyou100.xz.bean.User">
select
<!-- 引用相应的sql片段 -->
<include refid="usercolumns" />
from users
<if test="name!=null">
where name=#{name}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</select>
7. foreach 语句
<!-- delete from users where id in(?,?,?) -->
<delete id="deleteByIds">
delete from users where id in
<!--
collection:表示要遍历的集合名称
open:以(作为开始
close:以)作为结束
separator:每个元素之间使用,分割
item:每次遍历的值赋值给的变量名
-->
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
<!-- delete from users where id=1 or id=4 or id=6 -->
<delete id="delete">
delete from users
<!--
collection:表示要遍历的集合名称
open:以(作为开始
close:以)作为结束
separator:每个元素之间使用,分割
item:每次遍历的值赋值给的变量名
这里最好不要在foreach标签中用open="where " 因为当id等于0时,做全表删除时会报错
-->
<where>
<foreach collection="ids" separator="or" item="id">
id=#{id}
</foreach>
</where>
</delete>
八、逆向工程(generator)
通过前面的学习,在实际开发中,我们基本上能对mybatis应用自如了,但是我们发现了一个问题,所有操作都是围绕着po类,xxxMapper.xml文件,xxxMapper接口等文件来进行的。如果实际开发中数据库的表特别多,那么我们需要手动去写每一张表的po类,xxxMapper.xml,xxxMapper.java文件,这显然需要花费巨大的精力,而且可能由于表字段太多,写错了而不知道也是可能的。
所以我们在实际开发中,一般使用逆向工程方式来自动生成所需的文件,如dao,bean,xml映射文件 。
1.新建一个工程并导入jar包
2.创建generator.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration>
<!-- mysql驱动jar所在的位置 -->
<classPathEntry location="D:\\mysql\\mysql-connector-java-5.1.47.jar" /> <!-- 数据源的信息 -->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- 禁止所有注释 -->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis"
userId="root"
password="root">
</jdbcConnection> <javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生产的实体类所在的位置 -->
<javaModelGenerator targetPackage="com.zhiyou100.xz.bean" targetProject="./src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 生成的映射文件所在的位置 -->
<sqlMapGenerator targetPackage="com.zhiyou100.xz.mapper" targetProject="./resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 生产的dao文件所在位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.zhiyou100.xz.dao" targetProject="./src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 某张表与实体类的对应关系
schema:该表所在的数据库
tableName:表名
domainObjectName:实体类名
当需要多张表建立实体类时要建立多个table标签
-->
<table schema="mybatis" tableName="users" domainObjectName="Users"
enableCountByExample="false" enableSelectByExample="false" enableUpdateByExample="false" enableDeleteByExample="false">
<!--以Example结尾的属性全为false,是为了减少生成复杂的方法 -->
<property name="useActualColumnNames" value="true"/>
<generatedKey column="ID" sqlStatement="DB2" identity="true" />
<columnOverride column="DATE_FIELD" property="startDate" />
<ignoreColumn column="FRED" />
<columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />
</table> </context>
</generatorConfiguration>
3.运行主程序生成代码
package com.zhiyou100.xz.test; import java.io.File;
import java.util.ArrayList;
import java.util.List; import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback; public class Test {
public static void main(String[] args) throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("generator.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
九、分页助手(pagehelper)
1.导入jar包
2.在mybatis工程下的conf.xml中配置PageHelper的拦截器插件
<!--
plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
properties?, settings?,
typeAliases?, typeHandlers?,
objectFactory?,objectWrapperFactory?,
plugins?,
environments?, databaseIdProvider?, mappers?
-->
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
<property name="param1" value="value1"/>
</plugin>
</plugins>
3.先在UsersMapper.xml中写出查询所有的sql语句
<resultMap id="BaseResultMap" type="com.zhiyou100.xz.bean.Users">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="NAME" jdbcType="VARCHAR" property="NAME" />
<result column="age" jdbcType="INTEGER" property="age" />
<result column="sex" jdbcType="VARCHAR" property="sex" />
</resultMap>
<sql id="Base_Column_List">
id, NAME, age, sex
</sql>
<!-- 查询所有 -->
<select id="selectAll" resultMap="BaseResultMap">
select <include refid="Base_Column_List" /> from users
</select>
4.在接口UsersMapper中写 出查询所有的方法
package com.zhiyou100.xz.dao; import java.util.List; import com.zhiyou100.xz.bean.Users; public interface UsersMapper {
//查询所有用户
List<Users> selectAll();
}
5.测试运行
package com.test;
import java.io.Reader;
import java.util.ArrayList;
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.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhiyou100.xz.bean.Users;
import com.zhiyou100.xz.dao.UsersMapper;
class TestMybatis {
static SqlSession session=null;
final String str="com.zhiyou100.xz.mapper.UserMapper";
static UsersMapper usersMapper;
@BeforeAll
static void setUpBeforeClass() throws Exception {
//解析配置文件conf.xml
Reader reader=Resources.getResourceAsReader("conf.xml");
//获取SessionFactory对象
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader); //获取Session对象,表示jdbc中connection,操作数据库的
session=sessionFactory.openSession();
//得到接口的实现类
usersMapper=session.getMapper(UsersMapper.class);//相当于创建一个Dao对象
}
@Test
void testSelectByPage() {
// 1.使用PageHelper类设置起始页和每页显示的条数
int pageNum = 3;// 当前的页码 从网页中可以获取
int pageSize = 2;// pageSize:自定义
PageHelper.startPage(pageNum, pageSize); // 2.调用查询所有的方法
List<Users> list = usersMapper.selectAll();
System.out.println(list);
// 3.把查询的結果封裝到pageInfo对象中
PageInfo<Users> pageInfo = new PageInfo<>(list,3);
System.out.println(pageInfo);
//pageInfo.setNavigatePages(2);//setNavigatePages 设置每页显示的页码个数,这里这个属性没起作用
System.out.println("总页码:"+pageInfo.getPages());
System.out.println("当前页:"+pageInfo.getPageNum());
System.out.println("上一页:"+pageInfo.getPrePage());
int[] pages=pageInfo.getNavigatepageNums();//getNavigatepageNums显示页码的具体页数
for(int p:pages) {
System.out.print(p+"\t");
}
System.out.println("下一页:"+pageInfo.getNextPage());
List<Users> users=pageInfo.getList();
for(Users users2:users) {
System.out.println(users2);
} }
@AfterAll
static void tearDownAfterClass() throws Exception {
session.commit();//提交数据 事物管理:要么都执行,要么都不执行
}
}
十、$和#的区别
#{}
使用#{}意味着使用的预编译的语句,即在使用jdbc时的preparedStatement,sql语句中如果存在参数则会使用?作占位符,我们知道这种方式可以防止sql注入,并且在使用#{}时形成的sql语句,已经带有引号,例,select * from table1 where id=#{id} 在调用这个语句时我们可以通过后台看到打印出的sql为:select * from table1 where id='2' 加入传的值为2.也就是说在组成sql语句的时候把参数默认为字符串。
${}
使用${}时的sql不会当做字符串处理,是什么就是什么,如上边的语句:select * from table1 where id=${id} 在调用这个语句时控制台打印的为:select * from table1 where id=2 ,假设传的参数值为2
从上边的介绍可以看出这两种方式的区别,我们最好是能用#{}则用它,因为它可以防止sql注入,且是预编译的,在需要原样输出时才使用${},如,
select * from ${tableName} order by ${id} 这里需要传入表名和按照哪个列进行排序 ,加入传入table1、id 则语句为:select * from table1 order by id
如果是使用#{} 则变成了select * from 'table1' order by 'id' 我们知道这样就不对了。
<!-- $ Preparing:insert into users(name,age) values('吴立琪',18):完成sql拼接。Statement sql注入的缺陷
如果你传入的为列名或表名时可以使用$
# insert into users(name,age) values(?,?):防止sql的注入。PreparedStatement -->
<insert id="addUser" parameterType="com.zhiyou100.xz.bean.User" >
insert into users(name,age) values(#{name},#{age})
</insert>
十一、添加时如何获取添加成功后的主键值
Mybatis 配置文件 useGeneratedKeys 参数只针对 insert 语句生效,默认为 false。当设置为 true 时,表示如果插入的表以自增列为主键,则允许 JDBC 支持自动生成主键,并可将自动生成的主键返回。keyProperty是与主键对应的Java对象的属性名。
<!--
useGeneratedKeys="true" 表示使用字段生成的key
keyProperyty:把生产的key赋值到哪个属性上。
-->
<insert id="addUser1" parameterType="com.zhiyou100.xz.bean.User" useGeneratedKeys="true" keyProperty="id">
insert into users(name,age) values(#{name},#{age})
</insert>
@Test
void testAdd() {
User user=new User("张三",20);
session.insert(str+".addUser1", user);
int id=user.getId();//通过user对象中的getId()方法获取添加记录后返回自增列的值
System.out.println(id);
}
mybatis学习日志之总结的更多相关文章
- Mybatis学习日志
在Mybatis深入学习的一周中,总感觉跟着师傅的视屏讲解什么都能懂,但实际自己操作的时候才发现自己一脸懵逼,不知道从何入手.但还好自己做了点笔记.在此记录一下自己浅度学习Mybatis遇到几个小问题 ...
- Mybatis学习--日志
学习笔记,选自Mybatis官方中文文档:http://www.mybatis.org/mybatis-3/zh/logging.html Logging Mybatis内置的日志工厂提供日志功能,具 ...
- Mybatis学习-日志与分页
日志 为什么需要日志 如果一个数据库操作出现了异常,需要排错,那么日志就是最好的助手 Mybatis通过使用内置的日志工厂提供日志功能,有一下几种实现方式: SLF4J Apache Commons ...
- mybatis学习——日志工厂
为什么要使用日志工厂? 我们想一下,我们在测试SQL的时候,要是能够在控制台输出 SQL 的话,是不是就能够有更快的排错效率?答案是肯定的,如果一个 数据库相关的操作出现了问题,我们就可以根据输出的S ...
- mybatis学习日志二
一.动态sql语句 if语句 if+where语句 if+set语句 choose(when,otherwise)语句 trim语句 sql片段 foreach语句 总结 bean部分的User类代码 ...
- mybatis学习日志一
Mybatis 介绍 MyBatis 是支持 普通 SQL 查询 , 存储过程 和 高级映射 的优秀持久层框架.MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以 及对结果集的检索封装 ...
- MyBatis学习总结(八)——Mybatis3.x与Spring4.x整合(转载)
孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(八)--Mybatis3.x与Spring4.x整合 一.搭建开发环境 1.1.使用Maven创建Web项目 执行如下命令: m ...
- 【MyBatis学习笔记】
[MyBatis学习笔记]系列之预备篇一:ant的下载与安装 [MyBatis学习笔记]系列之预备篇二:ant入门示例 [MyBatis学习笔记]系列之一:MyBatis入门示例 [MyBatis学习 ...
- Mybatis学习笔记(二) 之实现数据库的增删改查
开发环境搭建 mybatis 的开发环境搭建,选择: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包.这些软件工具均可以到各自的官方网站上下载 ...
随机推荐
- React组件三大属性之 refs
React组件三大属性之 refs refs属性 1) 组件内的标签都可以定义ref属性来标识自己 a. <input type="text" ref={input => ...
- PAT乙级:1057 数零壹 (20分)
PAT乙级:1057 数零壹 (20分) 题干 给定一串长度不超过 105 的字符串,本题要求你将其中所有英文字母的序号(字母 a-z 对应序号 1-26,不分大小写)相加,得到整数 N,然后再分析一 ...
- POJ1723,1050,HDU4864题解(贪心)
POJ1723 Soldiers 思维题. 考虑y坐标,简单的货舱选址问题,选择中位数即可. 再考虑x坐标,由于直接研究布置方法非常困难,可以倒着想:不管如何移动,最后的坐标总是相邻的,且根据贪心的思 ...
- 第3天 IDEA 2021简单设置与优化 Java运算符 包机制
IDEA 2021简单设置与优化 将工具条显示在上方 View–>Appearance–>Toolbar 鼠标悬停显示 File–>setting–>Editor–>Ge ...
- Flask 之linux部署
1.装python > `[root ~]# yum install gcc [root ~]# wget https://www.python.org/ftp/python/3.6.5/Pyt ...
- (6java)计算机语言发展史
(6java)计算机语言发展史 机器语言: 程序是0和1的组合,比如:0000.0001.1100110 汇编语言: 程序比机器语言好理解一点点 高级语言: 比较适合老美,苦了英语差的孩子们了,哈哈. ...
- jvm源码解读--04 常量池 常量项的解析CONSTANT_Class_info
接上篇的继续 ConstantPool* constant_pool = ConstantPool::allocate(_loader_data, length, CHECK_(nullHandle) ...
- Linux下如何查看定位当前正在运行软件的配置文件
netstat命令 用于显示与IP.TCP.UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况 netstat -lntup 说明: l:listening n:num t:tc ...
- 【Android】真机调试新姿势:无线连接
由于工作需要,需要无线连接手机调试,特意百度了一下 在进行Android开发时,一般我们都是用usb线把手机和电脑连接起来进行调试工作.但如果你觉得这样不够酷的话,可以尝试一下无线连接,颇简单,GO! ...
- Linux 数据库操作(一)
我们可以将用于数据服务的数据库分为关系型数据库和非关系型数据库,关系型数据库最典型的就是Mysql,以及和他同源的MariaDB数据库,oracle等,非关系型数据库则有redis数据库,mongod ...