文档目录
(1)使用接口结合XML文件
(2)解决字段于属性不匹配
(3)链表查询
(4)Mybatis中 $ 和 # 的区别
(1)使用接口结合XML文件
1.创建实体类的接口,并写好根据id查询的方法
package com.zhiyou100.ydb.dao; import com.zhiyou100.ydb.bean.User; public interface UserDao { //创建根据id查询User信息 User GetUSer(int id); }
2.映射文件必须符合要求
3.测试方法
package com.zhiyou100.ydb.test; import static org.junit.jupiter.api.Assertions.*; 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.ydb.bean.User; import com.zhiyou100.ydb.dao.UserDao; class UserTest { static SqlSession session=null; final String str="com.zhiyou100.ydb.mapper.UserMapper"; @BeforeAll static void setUpBeforeClass() throws Exception { //解析配置文件 Reader reader = Resources.getResourceAsReader("conf.xml"); //获取session对象,表示Connection 用于操作数据库 SqlSessionFactory sessionFactory =new SqlSessionFactoryBuilder().build(reader); session = sessionFactory.openSession(); } @Test void SelectById() { UserDao userDao = session.getMapper(UserDao.class); !需要改变为使用接口调用方法! User user = userDao.GetUSer(1); System.out.println(user); } @AfterAll static void tearDownAfterClass() throws Exception { session.commit();//提交数据,事务管理 } }
多参数查询的方法
编写根据age的区间来查询的方法
在映射文件中编写sql语句
<select id="GetUser1" parameterType="map" resultType="com.zhiyou100.ydb.bean.User"> <![CDATA[select * from users where age >=#{min} and age <= #{max}]]> </select>
测试
package com.zhiyou100.ydb.test; import static org.junit.jupiter.api.Assertions.*; 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.ydb.bean.User; import com.zhiyou100.ydb.dao.UserDao; class UserTest { static SqlSession session=null; static UserDao userDao = null; @BeforeAll static void setUpBeforeClass() throws Exception { //解析配置文件 Reader reader = Resources.getResourceAsReader("conf.xml"); //获取session对象,表示Connection 用于操作数据库 SqlSessionFactory sessionFactory =new SqlSessionFactoryBuilder().build(reader); session = sessionFactory.openSession(); userDao = session.getMapper(UserDao.class); } @Test void SelectByage() { List<User> list = userDao.GetUser1(10, 20); System.out.println(list); } @AfterAll static void tearDownAfterClass() throws Exception { session.commit();//提交数据,事务管理 } }
遗憾的是结果并不是我们想要的:表示在找不到min ,可用的参数是0,1,param1,param2
解决:将映射文件sql语句中的条件名更改可用参数
那如果就是想用和dao方法中的参数名一样怎么办?
解决:在dao的该方法中使用@param(“参数名”) 因为:@param 表示告诉mybatis 封装到map中时,键的名字是什么
(2)解决字段于属性不匹配
1.建立一个Orders实体类
package com.zhiyou100.ydb.bean; public class Orders { private int id; private String no; private float price; //set get 方法 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } //构造方法 public Orders() { super(); } public Orders(String no, float price) { super(); this.no = no; this.price = price; } public Orders(int id, String no, float price) { super(); this.id = id; this.no = no; this.price = price; } //重写toString 方法 @Override public String toString() { return "Orders [id=" + id + ", no=" + no + ", price=" + price + "]"; } }
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:命名空间:用于区分各个Mapper.xml文件,必须和实体类接口全类名一致 --> <mapper namespace="com.zhiyou100.ydb.dao.OrdersDao"> <select id="getOrders" parameterType="int" resultType="com.zhiyou100.ydb.bean.Orders"> select * from orders where order_id=#{id} </select> </mapper>
3.在配置文件conf.xml中引入映射文件
4.测试
package com.zhiyou100.ydb.test; import static org.junit.jupiter.api.Assertions.*; import java.io.Reader; 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.ydb.bean.Orders; import com.zhiyou100.ydb.dao.OrdersDao; class OrdersTest { static SqlSession session=null; static OrdersDao ordersDao; @BeforeAll static void setUpBeforeClass() throws Exception { Reader reader = Resources.getResourceAsReader("conf.xml"); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); session= sessionFactory.openSession(); ordersDao = session.getMapper(OrdersDao.class); } @Test void SelectById() { Orders orders = ordersDao.getOrders(1); System.out.println(orders); } @AfterAll static void tearDownAfterClass() throws Exception { session.commit(); } }
结果是
而不是正确的数据库中的值,这是因为实体类中属性名称于数据库中的名称不相同所导致
解决方案(1)
给映射文件中的sql的每个字段起别名
解决方案(2)
使用resultMap标签
<!-- resultMap:属性与字段的对应关系 type:哪个实体类于表的对应关系 --> <resultMap type="com.zhiyou100.ydb.bean.Orders" id="OrdersMap"> <!-- id标签表示表中的主键于实体类中的属性的对应关系 --> <id column="order_id" property="id"/> <result column="order_no" property="no"/> <result column="order_price" property="price"/> </resultMap> <!-- resultMap于resultType只能出现一个 --> <select id="getOrders1" parameterType="int" resultMap="OrdersMap"> select * from orders where order_id=#{id} </select>
(3)链表查询
一对一/多对一查询
1.创建Clazz 和Teacher 的实体类
不要忘记set get 方法 构造方法
2.创建Clazzmapper映射方法
3.将映射文件加入到配置文件中
4.测试
5.也可以使用嵌套查询
多对以查询
1.在添加一个Student实体类,并且在Clazz实体类中加入Student是实体类,因为一个班级可以有多个学生,所以要加入的是Student实体类集合
2.编写dao方法
3.编写映射文件
4.测试
注意:在使用添加的功能时显示的id是0,一下操作可以将id返回
(4)Mybatis中 $ 和 # 的区别
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".
2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
3. #方式能够很大程度防止sql注入。
4.$方式无法防止Sql注入。
5.$方式一般用于传入数据库对象,例如传入表名.
6.一般能用#的就别用$.
MyBatis排序时使用order by 动态参数时需要注意,用$而不是#
字符串替换
默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。比如,像ORDER BY,你可以这样来使用:
ORDER BY ${columnName}
这里MyBatis不会修改或转义字符串。
重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。