1.使用mybatis完成CRUD
- 什么是CRUD?
- C:Create增
- R:Retrieve查(检索)
- U:Update改
- D:Delete删
- insert
<insert id="insertCar">
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values (null,'1003','丰田霸道',30.0,'2000-10-11','燃油车')
</insert>
<!--
这样写的问题是?
值 显然是写死到配置文件中的。
这个在实际开发中是不存在的。
一定是前端的form表单提交过来数据,然后将值传给sql语句
例如:JDBC的代码是怎么写的?
String sql = "insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)";
ps.setString(1,xxx);
ps.setString(2,yyy);
...
-->
- 在JDBC当中占位符采用的是?在mybatis当中是什么呢?
和?等效的写法是:#{}
在mybatis当中不能使用?占位符,必须使用 #{} 来代替JDBC当中的 ?
#{} 和JDBC当中的 ?是等效的 - java程序中使用Map可以给SQL语句的占位符传值:
Map<String,Object> map = new HashMap<>();
map.put("k1","1111");
map.put("k2","比亚迪汉");
map.put("k3",10.0);
map.put("k4","2020-11-11");
map.put("k5","电车");
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (null,#{k1},#{k2},#{k3},#{k4},#{k5})
/*注意:#{这里写什么?写map集合的key,如果key不存在,获取的是null}
一般map集合的key起名的时候要见名知意
Map<String,Object> map = new HashMap<>();
map.put("car_num","1111");
map.put("brand","比亚迪汉");
map.put("guide_price",10.0);
map.put("produce_time","2020-11-11");
map.put("car_type","电车");
<insert id="insertCar">
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (null,#{car_num},#{brand},#{guide_price},#{produce_time},#{car_type})
</insert>
*/
- java程序中使用POJO类给SQL语句的占位符传值
Car car = new Car(null, "3333", "比亚迪秦", 30.0, "2020-11-11", "新能源");
/*
注意:占位符#{},大括号里面写:pojo类的属性名
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values (null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
*/
把SQL语句写成这个德行:
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values (null,#{xyz},#{brand},#{guidePrice},#{produceTime},#{carType})
出现了什么问题?
There is no getter for property named ‘xyz’ in ‘class com.bjpowernode.mybatis.pojo.Car’
怎么解决的?
可以在Car类中提供一个getXyz()方法,这样问题就解决了。
通过这个测试,得出一个结论:
严格意义上来说:如果使用POJO对象传递值的话,#{}这个大括号中到底写什么?
写的是get方法的方法名去掉get,然后将剩下的单词首字母小写,然后放进去。
例如:getUsername --> #{username}
也就是说,mybatis在底层给?传值的时候,先要获取值,怎么获取的?
调用了pojo对象的get方法,例如:car.getCarNum()
- delete
- 需求:根据id删除数据,将id=17的数据删除
- 实现
int count = sqlSession.delete("deleteById",17); /* <delete id="deleteById"> delete from t_car where id = #{id} </delete> 注意:如果占位符只有一个,那么#{}的大括号里可以随意,但是最好见名知意 */
- update
- 需求:根据id修改某条记录
- 实现:
<!--update语句--> <update id="updateById"> update t_car set car_num = #{carNum}, brand = #{brand}, guide_price = #{guidePrice}, produce_time = #{produceTime}, car_type = #{carType} where id = #{id} </update> <!-- Car car = new Car(15l, "9999", "奥迪", 40.0, "2020-10-09", "燃油车"); int count = sqlSession.update("updateById", car); -->
- select(查一个,根据主键查询的话,返回的结果一定是一个)
- 需求:根据id查询
- 实现:
<select id="selectById" resultType="com.bjpowernode.mybatis.pojo.Car"> select * from t_car where id = #{id} </select> <!-- Object car = sqlSession.selectOne("selectById", 15); 需要特别注意的是:select标签中resultType属性,这个属性用来告诉mybatis,查询结果封装成什么类型的java对象 -->
- Car{id=15, carNum=‘null’, brand=‘奥迪’, guidePrice=null, produceTime=‘null’, carType=‘null’}
输出结果有点不对劲:
id和brand属性有值,其他属性为null - carNum以及其他的这几个属性没有附上值的原因是什么?
car_num、guide_price等这是查询结果的列名,这些列名和Car类中的属性名对不上
Car类的属性名:
carNum、guidePrice等 - 那这个问题怎么解决呢?
select语句查询的时候,查询结果集的列名是可以使用as关键字起别名的。
select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car where id = #{id}
- select(查所有的)
<select id="selectAll" resultType="com.bjpowernode.mybatis.pojo.Car">
select id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from t_car
</select>
/*
List<Object> cars = sqlSession.selectList("selectAll");
注意:resultType还是指定要封装的结果集的类型,不是指定List类型,是指定List集合中元素的类型
selectList方法:mybatis通过这个方法就可以得知你需要一个List集合,它会自动给你返回一个List集合
*/
- 在sql mapper.xml文件当中有一个namespace,这个属性是用来指定命名空间的,用来防止id重复。怎么用?
<!--在xml文件中-->
<mapper namespace="aaaaaa">
<select id="selectAll" resultType="com.bjpowernode.mybatis.pojo.Car">
select id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from t_car
</select>
</mapper>
<!--
在java程序中的写法:
List<Object> cars = sqlSession.selectList("aaaaaa.selectAll");
-->
- 实际上,本质上,mybatis中的sqlId的完整写法:
namespace.id
2.关于核心配置文件mybatis-config.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>
<!--<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/bjpowernode"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="123456"/>
</properties>-->
<!--resource,一定是从类路径下开始查找资源-->
<properties resource="jdbc.properties"></properties>
<!--从绝对路径当中加载资源。绝对路径怎么写?file:///路径-->
<!--<properties url="file:///d:/jdbc.properties"></properties>-->
<!--default表示默认使用的环境-->
<!--默认环境什么意思?当你使用mybatis创建SqlSessionFactory对象的时候,没有指定环境的话,默认使用哪个环境-->
<environments default="bjpowernode">
<!--
其中的一个环境,连接的数据库是bjpowernode
一般是一个数据库对应一个SqlSessionFactory对象
一个环境environment会对应一个SqlSessionFactory对象
-->
<environment id="bjpowernode">
<!--
transaction标签:
1.作用:配置事务管理器,指定mybatis具体使用什么方式去管理事务
2.type属性有两个值:
第一个:JDBC:使用原生的JDBC代码来管理事务
conn.setAutoCommit(false)
...
conn.commit();
第二个:MANAGED:mybatis不再负责事务的管理,将事务管理交给其他的JEE(JavaEE)容器来管理,例如:Spring
3.大小写无所谓,不区分大小写,但是不能写其他值,只能是二选一
jdbc、managed
4.在mybatis中提供了一个事务管理器接口:Transaction
该接口下有两个实现类:
JdbcTransaction
ManagedTransaction
如果type="JDBC",那么底层会实例化JdbcTransaction对象
如果type="MANAGED",那么底层会实例化ManagedTransaction对象
-->
<transactionManager type="JDBC"/>
<!--
dataSource配置:
1.dataSource被称为数据源
2.dataSource作用是什么?为程序提供Connection对象。(但凡是给程序提供Connection对象的,都叫做数据源)
3.数据源实际上是一套规范,JDK中有这套规范:javax.sql.DataSource(这个数据源的规范,这套接口实际上是JDK规定的)
4.我们自己也可以编写数据源组件,只要实现javax.sql.DataSource接口就行,实现接口当中所有的方法,这样就有了自己的数据源。
比如你可以写一个属于自己的数据库连接池(数据库连接池是提供连接对象的,所以数据库连接池就是一个数据源)
5.常见的数据源组件有哪些呢【常见的数据库连接池有哪些呢】?
阿里巴巴的德鲁伊连接池:druid
c3p0
dbcp
...
6.type属性用来指定数据源的类型,就是具体指定使用什么方式来获取Connection对象:
type属性有三个值:必须是三选一。
type="[UNPOOLED|POOLED|JNDI]"
UNPOOLED:不使用数据库连接池技术,每一次请求过来之后,都是创建新的Connection对象
POOLED:使用mybatis自己实现的数据库连接池
JNDI:集成其他第三方的数据库连接池
JNDI是一套规范,谁实现了这套规范呢?大部分的web容器都实现了JNDI规范:
例如:Tomcat、Jetty、WebLogic、WebSphere,这些服务器(容器)都实现了JNDI规范
JBDI是:java命名目录接口,Tomcat服务器实现了这个规范。
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--
提醒:正常使用连接池的话,池中有很多参数是需要设置的。设置好参数,可以让连接池发挥的更好。事半功倍的效果
具体连接池当中的参数如何配置呢?需要反复的根据当前业务情况进行测试
-->
<!--poolMaximumActiveConnections:连接池当中最多的正在使用的连接对象的数量上限。最多有多少个连接可以活动。默认值10-->
<property name="poolMaximumActiveConnections" value="10"/>
<!--每隔2秒打印日志,并且尝试获取连接对象-->
<property name="poolTimeToWait" value="2000"/>
<!--强行让某个连接空闲,超时时间的设置-->
<property name="poolMaximumCheckoutTime" value="10000"/>
<!--最多的空闲数量-->
<property name="poolMaximumIdleConnections" value="5"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--指定XxxMapper.xml文件的路径-->
<!--resource属性自动会从类的根路径下开始查找资源-->
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
3.使用dom4j解析XML文件
// 创建SAXReader对象
SAXReader reader = new SAXReader();
// 获取输入流
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
// 读XML文件,返回document对象。document对象是文档对象,代表了整个XML文件
Document document = reader.read(is);
//System.out.println(document);
// 获取文档当中的根标签
/*Element rootElement = document.getRootElement();
String rootElementName = rootElement.getName();
System.out.println("根节点的名字" + rootElementName);*/
// 获取default默认的环境id
// xpath是做标签路径匹配的,能够让我们快速定位XML文件中的元素。
// 以下的xpath代表了:从跟下开始找configuration标签,然后configuration标签下的子标签environments
String xpath = "/configuration/environments";
Element environments = (Element) document.selectSingleNode(xpath);
// 获取属性的值
String defaultEnvironmentsId = environments.attributeValue("default");
//System.out.println(defaultEnvironmentsId);
// 获取具体的环境environment
xpath = "/configuration/environments/environment[@id='"+defaultEnvironmentsId+"']";
Element environment = (Element) document.selectSingleNode(xpath);
// 获取environment节点下的transactionManager节点(Element的element()方法用来获取孩子节点)
Element transactionManager = environment.element("transactionManager");
String transactionType = transactionManager.attributeValue("type");
System.out.println("事务管理器的类型:" + transactionType);
// 获取dataSource节点
Element dataSource = environment.element("dataSource");
String dataSourceType = dataSource.attributeValue("type");
System.out.println("数据源的类型:" + dataSourceType);
// 获取dataSource节点下的所有子节点
List<Element> propertyElements = dataSource.elements();
// 遍历
propertyElements.forEach(propertyElement -> {
String name = propertyElement.attributeValue("name");
String value = propertyElement.attributeValue("value");
System.out.println(name + "=" + value);
});
// 获取所有的mapper标签
// 不想从根下开始获取,你想从任意位置开始,获取所有的某个标签,xpath该这样写
xpath = "//mapper";
List<Node> mappers = document.selectNodes(xpath);
// 遍历
mappers.forEach(mapper -> {
Element mapperElement = (Element) mapper;
String resource = mapperElement.attributeValue("resource");
System.out.println(resource);
});