将double数据,转换为只保留一位小数的double,四舍五入后的数据
notresult.setTotalDay(Double.parseDouble(String.format("%.1f", timts/8)));
pom.xml 添加如下过滤
<build> <resources> <resource> <directory>src/main/java/</directory> <includes> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build>
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">
<mapper namespace="org.mybatis.example.BlogMapper"> 这里就是mapper类
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</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> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> 控制台输出日志功能 <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?useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/example/mapper/UserMapper.xml"/> </mappers> resource是mapper文件的路径,是以"/" 为分割的,一个mapper标签指定一个mapper文件 </configuration>
@Test public void f() throws IOException { String con = "mybatis.xml"; //这个文件在resources目录 InputStream is = Resources.getResourceAsStream(con); SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is); SqlSession sqlsession = sf.openSession(); UserMapper mapper = sqlsession.getMapper(UserMapper.class); User userById = mapper.getUserById(); System.out.println(userById); sqlsession.close(); }
mybatis默认是不自动提交事务的,需要手动提交事务
<insert id="insertUser" >
insert into user values(#{id},#{name},#{pass}) </insert>
这里的 #{id} 等价于 getId()
mybatis底层是jdbc
配置模板文件步骤
FILE--->Settings--->Editor---> File and Code Templates--->右侧的 + 输入 Name 输入 Extension,填入 模板内容,点击Appply,点击OK,这样模板文件就生成好了,以后在想使用者模板的时候,点击New--->选择我们建立的模板名字就可以了
mapper的原理
mybatis框架,通过mapper.xml文件中的namespace,通过这个全限定类名建立这个mapper的动态代理类,通过代理类调用这个mapper中的方法,其实是去调用mapper.xml文件中的id为方法名的标签中的内容
Mapper中的 参数
resultType,在查询时才有用,其他情况不需要
parameterType,表示dao接口形参的类型,给mybatis使用的,这个属性的值可以是java类的全限定名称,或者mybatis指定的别名
已存在类型的别名在 mybatis – MyBatis 3 | 配置这里可以查看到
PreparedStatement ps = conn.preparStatement("select * from user where id =?");
ps.setint(1,id); 或者 ps.set("id",id);
mybatis可以通过反射机制,获取到mapper接口中 参数的类型,parameterType可以不写,写上之后会更规范,查看起来也方便
参数传递
1.只有一个java简单类型的 java的8大类型加上string类型时, #{任意字符} 大括号里面随意写参数名字
如 User getUserById(Integer id);
<select id ="getUserById" resultType="com.abc.pojo.User">
select * from user where id=#{id} //这里的id是随便写的
2.mapper接口中有两个及以上的java简单类型参数时,需要使用 Param命名参数注解
public List<User> getUserByNameOrId(@Param("myid") Integer id, @Param("myname") String name);
<select id="getUserByNameOrId" resultType="com.abc.pojo.User"> select * from user where id=#{myid} or name = #{myname} </select>
3.mapper接口中有多个参数时,需要使用一个java对象作为参数,对象的属性需要有get和set方法
public List<User> getUser(User user);
<select id="getUser" resultType="com.abc.pojo.User"> select * from user where id = #{id} or name = #{name} //这里的 #{id}等价于传进来的对象调用 getId()方法得到的值, #{name}等价于调用传进来的对象的getName()方法得到的值 </select>
4.mapper接口中有多个java简单类型参数,按照位置传递,从左到右依次为 arg0,arg1,arg2
#{arg0},#{arg1}
public List<User> getUserByNameOrId2(Integer id, String name);
<select id="getUserByNameOrId2" resultType="com.abc.pojo.User"> select * from user where id= #{arg0} or name = #{arg1} </select>
5.mapper接口中使用map作为参数
public List<User> getUserByMap(Map<String,Object> map);
Map<String,Object> map = new HashMap<>(); map.put("id",1001); map.put("name","李四"); List<User> list = mapper.getUserByMap(map);
<select id="getUserByMap" resultType="com.abc.pojo.User"> select * from user where id=#{id} or name = #{name} 这两个是map中的key </select>
占位符 # $
#号 #{}
<select id="get2" parameterType="java.lang.Integer" resultType="com.abc.pojo.User"> select * from user where id = #{id} </select>
mybatis使用#占位符,会使用PreparedStatement对象
PreparedStatement ps= conn.prepareStatement("select * from user where id=?");
ps.setInt(1,1001); //传递参数
ResultSet rs = ps.executeQuery();
特点 使用PreparedStatement,预编译,效率高,能防止sql注入
#{},作为列值使用,放在等号的右侧,#{}位置的值和类型有关
$号
${字符}
<select id="get2" parameterType="java.lang.Integer" resultType="com.abc.pojo.User">
select * from user where id = ${id}
</select>
${}:表示字符串连接,把sql语句的内容和 ${}的内容使用 字符串(+)连接在一起
select * from user where id = ${id} 等价于
String sql ="select * from user where id = " + "${id}",这里使用的是Statement对象,执行sql语句
Statement s = conn.createStatement();
ResultSet rs = s.execute(sql);
${}的特点
使用Statement对象,每次使用都得重新编译,使用的是字符串连接,有sql注入的风险,
${people},是按原样使用的,不会区分数据类型,${}常常用做表名或列名使用,在保证安全的情况下使用 ${} 举个例子
public List<User> getUserByName(@Param("name") String name);
<select id="getUserByName" resultType="com.abc.pojo.User"> select * from user where name = ${name} </select>
SqlSession session = MybatisUtils.getSqlSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list = mapper.getUserByName("'李四'");
这里的("'李四'") 必须是双引号里面包含着单引号,因为使用的是${},最后在sql拼接的时候回变成 select * from user where name = '李四',如果参数是("李四"),则最后拼劲的sql会变成
select * from user where name = 李四,这是李四会被做成数据表中的列名来使用,如果是整形的参数,则可以正常查询到数据。 Unknown column '李四' in 'where clause'
这里会涉及到sql注入的问题,如果把参数变成 ("'李四' or 1=1"),则最后拼接出来的sql会变成
select * from user where name = '李四' or 1=1 会查询到全部的数据,造成数据泄露或者,登录的时候的验证结果不对
总结一下
public List<User> getUserByName(@Param("id") Integer id,@Param("name") String name);
List<User> list = getUserByName(1000,"李四");
#{id} ,这里会涉及到类型,如果是整形,则在sql拼接时会加上 id=1000这样的
#{name},这里是String类型的,在sql拼接时,会加上 name='李四' 这样的
如果是 ${id},这里会涉及到类型,如果是整形,则在sql拼接时会加上 id=1000这样的
${name},这是String类型的,在sql拼接时,会加上 name= 李四 这样的,如果要加上
name='李四',这在传入name参数时应该是这样的
List<User> list = getUserByName(1000,"'李四'"); 里面加上单引号
${}的使用地方
我们在需要使用数据库中的列名或者表名的地方使用${}
如下的例子 mapper接口中的方法
public List<User> getUserByTableByColByParam(@Param("tableName") String tableName, @Param("colName1") String colName1, @Param("colName2") String colName2, @Param("name") String name, @Param("orderByName") String orderByName);
mapper.xml的定义
<select id="getUserByTableByColByParam" resultType="com.abc.pojo.User"> select ${colName1} , ${colName2} from ${tableName} where name = #{name} order by ${orderByName} </select>
${}传进来的参数是啥样,就替换为啥样, #{name}传进来的数据,如果是整形,则是原样,如果是String类型,则会在name的两边加上 ''单引号
调用这个方法测试
SqlSession session = MybatisUtils.getSqlSession(); UserMapper mapper = session.getMapper(UserMapper.class); List<User> list = mapper.getUserByTableByColByParam("user","name","password","李四","name"); for (User user : list) { System.out.println(user); }
resultType
封装查询结果,得到ResultSet,转换为java对象
<select id="getAll" resultType="com.abc.pojo.User"> select * from user </select>
resultType是select标签的属性,它的取值可以是java的全限定类名,或者是 别名
1.全限定类名
1.1 mybatis执行select标签中的sql语句,将ResultSet结果保存到java对象中,通过反射方式调用com.abc.pojo.User这个类的无参构造方法创建对象,User user = new User();
1.2 同名的列赋值给同名的属性
user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setPassword(rs.getString("password"));
1.3 得到java对象,如果mapper接口中返回的是List集合,mybatis会把对象放到List集合中去
自定义别名
mybatis提供的对java类型简短的标记
自定义别名的步骤
1.在mybatis.xml配置文件中,定义typeAlias标签
第一种方式
<typeAliases> <typeAlias type="com.abc.pojo.User" alias="user"></typeAlias> </typeAliases>
第二种方式,这里会把com.abc.pojo包下的类名全部类的类名作为别名,这里的别名不区分大小写,这里需要注意,如果存在两个相同的类名时,当这两个类作为resultType时会报错,mybatis区分不出来需要用哪个类
<typeAliases> <package name="com.abc.pojo"/> </typeAliases>
2.在mapper.xml文件中使用定义的这个别名
resultType="user"
resultType返回 java对象
public List<User> getUserById(@Param("id") Integer id);
<select id="getUserById" resultType="com.abc.pojo.User"> select * from user where id = #{id} </select>
resultType返回简单类型 返回的数据是一行一列
<select id="getCount" resultType="java.lang.Long"> select count(*) from user </select>
resultType返回Map数据结构
mybatis执行sql语句,把ResultSet转换为Map数据结构
public Map<Object,Object> getMap(@Param("id") Integer id);
<select id="getMap" resultType="java.util.HashMap"> select * from user where id = #{id} </select>
SqlSession session = MybatisUtils.getSqlSession(); UserMapper mapper = session.getMapper(UserMapper.class); Map<Object,Object> map = mapper.getMap(1001);
mapper.xml中sql语句的列名作为map的key,查询结果中的列值作为map中key对应的value的值
使用Map作为返回结果时,最多只能返回一行数据,多余一行mybatis会报错
ResultMap
解决数据库中查询出来的字段和java对象中属性字段不同名的问题
1.在sql查询语句中使用别名,把查询出来不同名的字段变成和java对象中属性名一致
2.使用resultMap标签,修改不同名的字段
like的使用
方式1
public List<User> getUserByLikeOne(@Param("name") String name);
<select id="getUserByLikeOne" resultType="com.abc.pojo.User"> select * from user where name like #{name} </select>
这种情况需要在给这个方法传入参数时,提前设置好name的值,配置好%; 如下
String name = "%"+"李"+"%"; List<User> list = mapper.getUserByLikeOne(name);
方式2
public List<User> getUserByLikeTwo(@Param("name") String name);
在拼接sql语句时,加上两个 "%" 用空格分开 #{}
<select id="getUserByLikeTwo" resultType="com.abc.pojo.User"> select * from user where name like "%" #{name} "%" </select>
String name = "李"; //这里不需要拼接%了 List<User> list = mapper.getUserByLikeTwo(name);
动态sql
<if> 一般在where查询条件后面加上 1=1
<if test="boolean结果"> and name = #{name} </if>
public List<User> getUserByIf(User user);//这里必须是对象
<select id="getUserByIf" resultType="com.abc.pojo.User">
select * from user where 1=1 //where后面加上 1=1
<if test="name!=null and name!=''">
and name = #{name}
</if>
<if test="id!=null and id>0">
or id = #{id}
</if>
</select>
mapper.xml文件中如果需要使用 大于,小于号这样的,需要 查找 这些字符的 html实体
<where>标签
public List<User> getUserByWhere(User user); //这里是对象
<select id="getUserByWhere" resultType="com.abc.pojo.User"> select * from user <where> <if test="name!=null and name!=''"> name = #{name} </if> <if test="id!=null and id>0"> or id = #{id} </if> </where> </select>
foreach标签
<foreach collection="集合的类型" open="开始的字符" close="结束的字符" separator="分割的字符" item="集合中的成员">
#{集合中的成员} </foreach>
collection:表示循环的是数组还是list集合,如果mapper接口中方法的形参是数组,则collection="array" ,如果mapper接口中方法的形参是list集合,则collection="list"
open:循环开始的字符 (
close:循环结束时的字符 )
item:集合的成员
separator:集合成员之间的分割符 ,
循环简单list集合
public List<User> getUserByForEach(List<Integer> list);
<select id="getUserByForEach" resultType="com.abc.pojo.User"> select * from user <if test="list!=null and list.size>0"> where id in <foreach collection="list" open="(" separator="," close=")" item="myid"> #{myid} </foreach> </if> </select>
循环复杂list集合 list集合中存放的是java对象
public List<User> getUserByForEachUser(List<User> list);
<select id="getUserByForEachUser" resultType="com.abc.pojo.User"> select * from user <if test="list!=null and list.size>0"> where id in <foreach collection="list" open="(" separator="," close=")" item="us"> 这里是集合中的对象 #{us.id} 这里是对象里面的属性 </foreach> </if> </select>
trim标签的使用
public int insertByIf(User user);
<insert id="insertByIf"> insert into user <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id!=null and id>0">id,</if> <if test="name!=null and name!=''">name,</if> <if test="password!=null and password!=''">password,</if> </trim> <trim prefix="values(" suffixOverrides="," suffix=")"> <if test="id!=null and id!=''">#{id},</if> <if test="name!=null and name!=''">#{name},</if> <if test="password!=null and password!=''">#{password},</if> </trim> </insert>
set标签 update使用方法1
public int updateByTrim(User user);
<update id="updateByTrim"> update user <set> <if test="name!=null and name!=''">name=#{name},</if> <if test="password!=null and password!=''">password=#{password},</if> </set> where id = #{id} </update>
update方法2
public int updateBySet(User user);
<update id="updateBySet" > update user <trim prefix="set " suffixOverrides=","> <if test="name!=null and name!=''">name=#{name},</if> <if test="password!=null and password!=''"> password=#{password}, </if> </trim> where id=#{id} </update>
mybatis.xml配置文件
<typeAliases> <package name="org.example.pojo"/><!--配置实体类的别名--> </typeAliases>
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/><!--事务管理器类型,type=JDBC由mybatis完成处理事务,type=MANAGED管理,表示把事务交给容器处理,交给其他软件完成事务的提交,回滚 --> <dataSource type="POOLED"> <!--这里mybatis会使用POOLEDDataSource--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments>
dataSource:数据源 属性type指的是数据源的类型
type=POOLED,表示mybatis会在内存中创建PooledDataSource,管理多个connection对象,使用的是连接池, type=UNPOOLED,不适用连接池,每次执行sql语句时会先创建connection对象,执行sql,关闭连接
添加properties标签
<properties resource="jdbc.properties"> resource属性表示使用类路径下的文件
</properties>
mapper标签,使用package,必须保证mapper接口名和mapper.xml文件名一样,并且在同一个包下 ,resource表示从类路径开始的哪个文件
<mappers>
<!-- <mapper resource="org/example/mapper/UserMapper.xml"/>-->
<package name="org.example.mapper"/>
</mappers>
MYBATIS 一个实体类中含有其他类属性和list属性
<resultMap id="restmap2" type="com.abc.springbootmybatis.pojo.UserAndUser1"> <!-- 这两个是类的属性 --> <id property="id" column="id"/> <result property="name" column="name"/> <!-- 这个是引用类型的属性 --> <association property="user2" javaType="com.abc.springbootmybatis.pojo.User2"> <result property="id" column="u2id"/> <result property="name" column="u2name"/> </association> <!-- 这里是包含一个集合 --> <collection property="user1List" ofType="com.abc.springbootmybatis.pojo.User1"> <result column="uid" property="id"/> <result column="uage" property="age"/> </collection> </resultMap> <select id="getUserAndUser2" resultMap="restmap2"> select user.id as id, user.name as name, user1.id as uid, user1.age as uage, user2.id as u2id, user2.name as u2name from user left join user1 on user.id = user1.age left join user2 on user.id =user2.id where user.id = #{idd} </select>
public class User1 { private Integer id; private Integer age;}
public class User2 { private Integer id; private String name;}
public class UserAndUser1 { private Integer id; private String name; private User2 user2; private List<User1> user1List;}