今日内容
1. MyBatis日志
MyBatis日志 日志是我们纠察改错的有力工具 1)导入日志的jar包--使用log4j 2)配置日志的核心配置文件 3)将日志输出并查看
2. 不适用MyBatis自带的连接池,使用德鲁伊
MyBatis的连接池来源 -PooledDataSourceFactory是MyBatis自带的数据源工厂 -无参构造,创建了默认的连接池 替换成我们自己的-德鲁伊 -创建一个类继承PooledDataSourceFactory-相当于创建了自己的工厂 -无参构造,替换我们自己的数据源
package com.szr.dataSource;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
//自定义类继承了MyBatis自带的连接池
public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
//进行无参构造替换数据源
public MyDruidDataSourceFactory(){
//将MyBatis的数据源替换成德鲁伊的数据源
this.dataSource = new DruidDataSource();
}
}
3. 优化MyBatis的核心配置文件
优化 1)优化连接数据库 在MyBatis入门中,我们连接数据库使用的是自带的连接池,现在替换成德鲁伊 所有连接数据库需要的参数都是写死的--用户名,密码 -这不利于日后维护和修改数据 所以书写连接数据库的配置文件,所有数据从配置文件中取用,需要时只需要更改配置文件内容即可 2)优化实体类的全限定名称 当我们需要使用实体类时--自定义类时,需要写出全限定名称 -提供typeAlias来使用别名 -alias:别名 -type:要起名字的类的全限定名称 但是--换汤不换药--如果有20个类需要起别名,依然很劳神费力 所以--实体类的包扫描! <package name="存放所有实体类的包的包名"/> 将类集中起来同一起别名--默认为当前类的类名,并且不区分大小写! 3)优化映射器 和实体类类似,每有一个接口--就需要一个映射文件来实现功能 一个一个创建工作量大,耗时 所以--接口文件的包扫描! <package name="存放所有接口的包的包名"/> 将包内所有的接口都作为映射器--和映射文件一一对应!
<?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="druid.properties"></properties>
<!--配置实体类别名-->
<typeAliases>
<!--老方法,单独配置-->
<!--<typeAlias alias="user" type="com.szr.pojo.User"></typeAlias>-->
<!--<typeAlias alias="product" type="com.szr.pojo.Product"></typeAlias>-->
<!--包扫描方法-->
<package name="com.szr.pojo"/>
</typeAliases>
<!--配置MyBatis环境-->
<environments default="mysql"><!--默认环境为mysql-->
<environment id="mysql"><!--环境名称mysql-->
<!--mybatis控制事务管理器-->
<transactionManager type="JDBC"></transactionManager>
<!--mybatis数据源,替换为德鲁伊-->
<dataSource type="com.szr.dataSource.MyDruidDataSourceFactory">
<!--配置数据库连接信息,原来是写死的,现在从配置文件中获取-->
<!--这里的${名称}要和配置文件中的key值相同-->
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<!--其他配置属性,最大连接数,初试连接数,等待时间-->
<property name="maxActive" value="${maxActive}"/>
<property name="initialSize" value="${initialSize}"/>
<property name="maxWait" value="${maxWait}"/>
</dataSource>
</environment>
</environments>
<!--映射器-->
<mappers>
<!--配置包扫描-->
<package name="com.szr.mapper"/>
</mappers>
</configuration>
4. MyBatis映射文件
MyBatis 映射文件如何实现多条件查询--总的来说,都是先将数据封装,然后再取用 1)占位符号查询--方法不实用,容易出错,不建议使用 实体属性参数和占位符好一一对应,类似于"?" 2)通过参数绑定--一般 @param("绑定名称") 参数类型 参数名称 -相当于把参数和一个自己起的名称绑定在一起,然后使用 3)Map集合添加多个参数--常用! 将参数类型和参数名称以键值对的形式存入map,然后取用 4)将用户实体包装,然后调用当中的属性来传入多个条件
4.1 查询用户
4.1.1 包装实体类
package com.szr.vo;
import com.szr.pojo.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//封装用户实体,方便查询取用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QueryVo {
private User user ;
}
4.1.2 接口类
package com.szr.mapper;
import com.szr.pojo.User;
import com.szr.vo.QueryVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
//用户的增删改查
public interface UserMapper {
/**
* 查询所有用户--集合取出
* @return 返回用户集合
*/
List<User> findAllUser();
/**
* 根据用户名和性别查找用户--param
* @param username 用户名
* @param gender 性别
* @return 返回用户
*/
User selectUserByParam(@Param("name") String username,@Param("sex") String gender);
/**
* 根据用户名和性别查找用户--map
* @param map 存入了数据的集合
* @return
*/
User selectUserByMap(Map<String,String> map);
/**
* 根据用户名和性别查找用户--包装实体类
* @param vo 包装的类的对象
* @return
*/
User selectUserByOv(QueryVo vo);
}
4.1.3 用户映射文件
<?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="com.szr.mapper.UserMapper">
<!--创建一个集合,相当于都可以用的公共集合,以后都建议使用这种方式!-->
<!--id 代表这个集合的唯一标识; type 实体类的别名,之前的核心配置文件中,包扫描了接口包,并创建了别名,不区分大小写-->
<resultMap id="baseMap" type="user">
<!--
property 属性名称,是实体类里的名称;
colum 列表字段,是数据库中的列表字段
集合解决了属性名称和列表字段不一样的问题-存为key和value!
当然也可以一样!
-->
<!--id配置的主键字段-->
<id property="id" column="id"></id>
<!--其他字段-->
<result property="username" column="username"></result>
<result property="gender" column="gender"></result>
<result property="age" column="age"></result>
<result property="address" column="address"></result>
</resultMap>
<!--高级映射输出-->
<!--查询结果存入事先准备的集合中-->
<select id="findAllUser" resultMap="baseMap">
select * from user
</select>
<!--param多参数查询-->
<select id="selectUserByParam" resultMap="baseMap">
<!--这里的name和sex就是接口绑定的参数的绑定名称-->
select * from user where username = #{name} and gender = #{sex}
</select>
<!--Map多参数查询-->
<!--传入一个参数,map集合-->
<select id="selectUserByMap" parameterType="java.util.Map" resultMap="baseMap">
select * from user where username = #{username} and gender = #{gender}
</select>
<!--包装实体类传入多个参数-->
<select id="selectUserByOv" parameterType="com.szr.vo.QueryVo" resultMap="baseMap">
select * from user where username = #{user.username} and gender = #{user.gender}
</select>
</mapper>
4.1.4 测试类--单元测试
package com.szr.test;
import com.szr.mapper.UserMapper;
import com.szr.pojo.User;
import com.szr.vo.QueryVo;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
//测试查询
public class MybatisTest {
private SqlSessionFactory factory ;
private SqlSession session ;
private UserMapper userMapper ;
@Before
public void prepared() throws IOException {
//通过流的方式获取配置文件内容
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//创建构造者
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//构造者使用配置文件构造工厂类
factory = builder.build(inputStream);
//创建执行对象
session = factory.openSession();
//调用接口
userMapper = session.getMapper(UserMapper.class);
}
/**
* 查询所有用户信息
*/
@Test
public void testFindAll(){
List<User> users = userMapper.findAllUser();
if(users!=null){
for (User user : users) {
System.out.println(user);
//User(id=1, username=钟离, gender=男, age=500, address=往生堂)
//User(id=2, username=胡桃, gender=女, age=18, address=往生堂)
}
}
session.commit();
}
/**
* 根据用户姓名和性别查找用户--参数绑定
*/
@Test
public void testFindUserByParam(){
//调用方法
User user = userMapper.selectUserByParam("钟离", "男");
System.out.println(user);
//User(id=1, username=钟离, gender=男, age=500, address=往生堂)
session.commit();
}
@Test
public void testFindUserByMap(){
//创建数据集合
Map<String,String> map = new HashMap<>();
//存入条件--映射时根据存入的key来获取value
map.put("username","胡桃");
map.put("gender","女");
//调用方法
User user = userMapper.selectUserByMap(map);
System.out.println(user);
//User(id=2, username=胡桃, gender=女, age=18, address=往生堂)
session.commit();
}
/**
* 根据用户名和性别查找用户--包装实体的类作为数据
*/
@Test
public void testFindUserByQueryVo(){
//调用包装类
QueryVo queryVo = new QueryVo();
//创建数据
User user = new User();
user.setUsername("钟离");
user.setGender("男");
//封装数据
queryVo.setUser(user);
//调用方法
User user1 = userMapper.selectUserByOv(queryVo);
System.out.println(user1);
//User(id=1, username=钟离, gender=男, age=500, address=往生堂)
session.commit();
}
@After
public void close(){
//释放资源
session.close();
}
}
4.2 注解方式--不需要书写xml文件
注解方式 直接在接口上使用注解方式,完成操作
4.2.1 商品实体类
package com.szr.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//商品实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
private Integer pid ; //商品编号
private String pname ; //商品名称
private Integer pprice ; //商品价格
private String pdesc ; //商品描述
}
4.2.2 商品接口
package com.szr.mapper;
import com.szr.pojo.Product;
import org.apache.ibatis.annotations.Select;
//用户的增删改查
public interface ProductMapper {
/**
* 查询所有商品
* @return 返回商品实体
*/
@Select("select * from product")
Product findAllProduct();
}
4.2.3 测试
@Test
public void testFindAllProduct(){
//直接调用接口
ProductMapper productMapper = session.getMapper(ProductMapper.class);
//执行方法
List<Product> allProduct = productMapper.findAllProduct();
//遍历
for (Product product : allProduct) {
System.out.println(product);
//Product(pid=1, pname=贯虹之朔, pprice=6480, pdesc=加攻击力的武器)
//Product(pid=2, pname=护摩之杖, pprice=6480, pdesc=加爆伤的武器
}
}