MyBatis-Day2

第1章 回顾mybatis的自定义再分析和环境搭建

自定义开发流程图

 回顾mybatis环境搭建步骤

第一步:创建 maven 工程 

新建普通java工程day02_mybatis,在下面新建maven模块day02_eesy_01mybatisCRUD

第二步:导入坐标

出的问题,写dependency无提示信息,报红是点击右侧提示选update就有了。然后还是写了以后红波浪,就clean和reimport刷新解决,没有改VM先让它找本地对应有的,明明本地有为啥不自动去找!!

dependency用了log4j日志工具要把log4j.properties放到res下

第三步:编写必要代码实体类和持久层接口

 User.java 和 IUserDao接口

第四步:编写 SqlMapConfig.xml

需要拷贝一下头部信息粘贴

第五步:编写映射配置文件IUseDao.xml

也需要拷贝一下头部信息粘贴

 <!--id映射查询所有方法  resultType="com.xxw.domain.User"写把结果类型-->
<select id="findAll" resultType="com.xxw.domain.User">
    select * from user;
</select>

第六步:编写测试类 MybatisTest

使用了@Test替代昨天的main方法(就方法名上@Test无需main了直接写就是,每个@Test可以直接运行

/**
* 测试查询所有方法(用代理类生成IUserDao接口的的代理对象)
*/
@Test
public void testFindAll() throws Exception {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//builder生成工厂
SqlSession sqlSession = factory.openSession();//工厂生产sqlSession对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);//session获取接口的代理类
List<User> users = userDao.findAll();

for(User user:users){
System.out.println(user);
}
sqlSession.close();
in.close();
}

运行查找所有数据输出成功,昨天的环境又重新搭建成功

第2章 基于代理 Dao 实现 CRUD 操作 

就还是使用上面那个maven模块day02_eesy_01mybatisCRUD

 开始在中增加对数据库增删改查的方法

先写一个增加用户保存到数据库的方法,对应的IUserDao接口类增加saveUser抽象方法

/**
* 保存用户 插入一条数据
* @param user
*/
void saveUser(User user);

对应的IUserDao.xml增加匹配方法的sql语句

<!-- 映射保存用户方法 参数类型就是插入数据的类型。插入是一条实体类的数据#号{}号 里面写每一个插入数据实体类对象的属性-->
<insert id="saveUser" parameterType="com.xxw.domain.User">
    insert into user(username,address,sex,birthday)values(#{userName},#{userAddress},#{userSex},#{userBirthday});
</insert>

然后在测试类MybatisTest用@Test注解测试saveUser方法

由于又要重复获取IUserDao接口代理类的代码操作和释放资源操作(和testFindAll时一样),所以把这两部分代码封装一下并借助@before和@after实现每一个@test之前之后都执行这两部分代码。

public class MybatisTest {

    private InputStream in;
    private SqlSession sqlSession;
    private IUserDao userDao;

    @Before//用于在测试方法执行之前执行(把那些重复的构建工厂获取代理的代码放到@before里面)
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取SqlSession对象
        sqlSession = factory.openSession();
        //4.获取dao的代理对象
        userDao = sqlSession.getMapper(IUserDao.class);
    }

    @After//用于在测试方法执行之后执行(重复的释放资源操作)
    public void destroy()throws Exception{
        //提交事务!不然sava没有提交就会自动回滚
        sqlSession.commit();
        //6.释放资源
        sqlSession.close();
        in.close();
    }

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll(){
        //5.执行查询所有方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
    }

    /**
     * 测试保存操作
     */
    @Test
    public void testSave(){//特别注意:执行方法后要进行提交事务的操作。
        User user = new User();
        user.setUserName("modify User property");
        user.setUserAddress("北京市顺义区");
        user.setUserSex("男");
        user.setUserBirthday(new Date());
        //5.执行保存方法
        userDao.saveUser(user);
    }

}
MybatisTest.java

运行结果:表格后面插入了一条49号数据,id是自增的

更新某条用户数据方法

IUserDao.xml

<!--也是和插入一样传入了参数所以要写参数类型-->

<update id="updateUser" parameterType="com.xxw.domain.User">
update user set username=#{userName},address=#{userAddress},sex=#{userAex},birthday=#{userBirthday} where id=#{userId}
</update>

测试类MybatisTest
@Test
public void testUpdate(){

User user = new User();
user.setUserId(49);
user.setUserName("xxw user");
user.setUserAddress("北京市海淀区");
user.setUserSex("女");
user.setUserBirthday(new Date());
//5.执行更新方法
userDao.updateUser(user);

}

运行结果:49号被重新更新数据了(保存插入只能在最末尾,更新可以任意id更新

根据id删除某条数据

IUserDao接口

/**
* 根据Id删除用户
* @param userId
*/
void deleteUser(Integer userId);

IUserDao.xml
<!--根据id删除用户 sql语句中id的#{}里面只是一个占位符,传啥都行反正参数只有一个啥都是该参数-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{uid}
</delete>
测试类MybatisTest
/**
* 测试删除操作
*/
@Test
public void testDelete(){

//5.执行删除方法
userDao.deleteUser(43);

}

运行结果:43号数据被删除

根据id查询用户数据

IUserDao.xml

<!--根据id查询用户有传入参数,也有返回值 都要写清楚类型-->
<select id="findById" parameterType="INT" resultType="com.xxw.domain.User">
select * from user where id = #{uid}
</select>
测试类MybatisTest
/**
* 测试根据id查询用户信息操作
*/
@Test
public void testFindOne(){
//5.执行查询一个方法
User user = userDao.findById(49);
System.out.println(user);
}

运行结果:49号数据查找成功

根据用户名模糊查询

IUserDao接口

/**
* 根据名称模糊查询用户信息
* @param username
* @return
*/
List<User> findByName(String username);

IUserDao.xml
<!--根据名称模糊查询 与id查询的区别是用like代替等号-->
<select id="findByName" parameterType="string" resultType="com.xxw.domain.User">
select * from user where username like #{name}
--     select * from user where username like '%${value}%' 这样写也可以
</select>
测试类MybatisTest
/**
* 测试模糊查询操作
*/
@Test
public void testFindByName(){
//5.执行查询一个方法
List<User> users = userDao.findByName("%王%");
//        List<User> users = userDao.findByName("王"); 这样用对应上面那样写
for(User user : users){
System.out.println(user);
}
}

运行结果:成功把数据库中用户名中带王自的行数据查找出来

聚合函数

查询总用户数

IUserDao接口

/**
* 查询总用户数
* @return
*/
int findTotal();

IUserDao.xml
<select id="findTotal" resultType="int">
select count(id) from user;
</select>
测试类MybatisTest
/**
* 测试查询总记录条数
*/
@Test
public void testFindTotal(){
//5.执行查询一个方法
int count = userDao.findTotal();
System.out.println(count);
}

运行结果:6条

MybatisCRUD-保存操作的细节-获取保存数据的ID

sql:select last_insert_id();

IUserDao.xml
<!-- 映射保存用户方法 参数类型就是插入数据的类型。插入是一条实体类的数据#号{}号 里面写实体类对象的属性-->
<insert id="saveUser" parameterType="com.xxw.domain.User">
<!--增加配置插入操作后,获取插入数据的id-->
<selectKey keyProperty="userId" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,address,sex,birthday)values(#{userName},#{userAddress},#{userSex},#{userBirthday});
</insert>
测试类MybatisTest
/**
* 测试保存操作
*/
@Test
public void testSave(){//特别注意:执行方法后要进行提交事务的操作。
User user = new User();
user.setUserName("modify User property");
user.setUserAddress("北京市顺义区");
user.setUserSex("男");
user.setUserBirthday(new Date());
System.out.println("保存操作之前:"+user);//保存前id是null!!!
//5.执行保存方法
userDao.saveUser(user);
System.out.println("保存操作之后:"+user);//运行结果:插入用户保存后有了该条保存的id!!!!

第3章 Mybatis 的参数深入

Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo的属性名称。

(感觉有点像jsp里的el表达式直接写属性名取值...长得都类似...

听不太懂,求助同学的博客...

ParameterType可以传递:

1.简单类型,int,String等

2.pojo对象(即javabean)?所以pojo类就是实体类的意思!

使用ognl表达式解析对象字段的值。如:#{pojo属性名称}

OGNL表达式:object graphic navigation language,对象图导航语言。通过对象的取值方法来获取数据,在写法上把get省略了。如:user.username。

开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。 Pojo 类中包含 pojo。 需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。 (多个查询条件用一个查询条件参数vo对象)

IUserDao接口

    /**
* 根据queryVo中的条件查询用户
* @param vo
* @return
*/
List<User> findUserByVo(QueryVo vo);
}

3.pojo包装对象

 1.main/java/domain中创建一个QueryVo类,定义一个user类的私有属性,并生成getters&setters:

public class QueryVo {//查询条件类 是包装User实体类而来
private User user;

public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

 2.IUserDao.xml增加

<!-- 根据queryVo的条件查询用户 参数是一个查询条件类,是包装实体类而成,即把实体类做成属性-->
<select id="findUserByVo" parameterType="com.xxw.domain.QueryVo" resultType="com.xxw.domain.User">
select * from user where username like #{user.userName}
用途就是like这儿可以放表的其他属性?就是用什么属性查数据的时候只需要改这里不需要再去接口写方法?或者别的表别的属性也只需改这儿?个人理解
</select>

 3.MybatisTest中写测试

    /**
* 测试使用QueryVo作为查询条件
*/
@Test
public void testFindByVo(){
QueryVo vo = new QueryVo();
User user = new User();
user.setUserName("%王%");//百分号是为了模糊
vo.setUser(user);
//5.执行查询一个方法
List<User> users = userDao.findUserByVo(vo);
for(User u : users){
System.out.println(u);
}
}
}

运行结果:模糊查询出3条名字包含王的User类数据

第4章 Mybatis 的输出结果封装 (结果集的深入)

由于我的实体类属性名与数据库不匹配,只有userName属性和数据库username列由于window不区分大小写可以被查出来,其他三个属性查出来打印的值都是null...

User{userId=null, userName='老王', userAddress='null', userSex='null', userBirthday=null}

User{userId=null, userName='小二王', userAddress='null', userSex='null', userBirthday=null}

User{userId=null, userName='传智播客', userAddress='null', userSex='null', userBirthday=null}

User{userId=null, userName='老王', userAddress='null', userSex='null', userBirthday=null}

User{userId=null, userName='小马宝莉', userAddress='null', userSex='null', userBirthday=null}

User{userId=null, userName='xxw user', userAddress='null', userSex='null', userBirthday=null}

User{userId=null, userName='modify User property', userAddress='null', userSex='null', userBirthday=null}

但是增删改不影响,在数据库中操作不需要返回数据库中,实体类的属性和数据库列名不一样也可以。

如何解决查询find出的问题呢?

1.sql语句中对实体类属性取别名

比如在IUserDao.xml改findAll的sql:select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;

2.Mybatis提供一种在IUserDao.xml中配置查询结果的列名和实体类的属性吗的对应关系

 <!--配置 查询结果的列名和实体类的属性名的对应关系 -->
<resultMap id="userMap" type="com.xxw.domain.User">
<!-- 主键字段的对应 -->
<id property="userId" column="id"></id>
<!--非主键字段的对应-->
<result property="userName" column="username"></result>
<result property="userAddress" column="address"></result>
<result property="userSex" column="sex"></result>
<result property="userBirthday" column="birthday"></result>
</resultMap>

然后resultType不要了改成resultMap

     <!--id映射查询所有方法  resultType="com.xxw.domain.User"写把结果类型-->
<select id="findAll" resultMap="userMap">改这里!!
-- select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;
select * from user;
</select>

其他查询操作也都只要改为resultMap="userMap"就可以,这对于查询操作较多的操作起来方便一些,但效率没有起别名只用改sql高。

(当然效率最高的还是是实体类类名与数据库列名写成一样的。。。

第5章 Mybatis 传统 DAO 层开发(编写dao的实现类)[了解] 

之前学javaweb时用的都是写实现类。Dao一个接口一个实现类,Service层一个接口一个实现类。

第6章 SqlMapConfig.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>
    <!--这是mybatis的主配置文件-->
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql的环境-->
        <environment id="mysql">
            <!--配置事务类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
                <property name="username" value="root"></property>
                <property name="password" value="root"></property>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--xml配置映射文件-->
        <mapper resource="com/xxw/dao/IUserDao.xml"></mapper>
    </mappers>
</configuration>
View Code

properties标签

加入<properties>就把配置连接数据库的基本信息的带<property> 标签的都复制到<properties>里面去,然后给原来的value用${}引用

用处就是可以把<properties>里面的带<property> 标签的内容放到外面放一个jdbcConfig.properties文件里。这个SqlMapConfig.xml里面就只剩<property>原来的value用${}引用就可以。

typeAliases标签 ---解释Integer的写法

<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<!--typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名后IUserDao.xml就不再区分大小写 -->
<typeAlias type="com.itheima.domain.User" alias="user"></typeAlias>

</typeAliases>

IUserDao.xml中的parameterType="com.xxw.domain.User"就可以=“user"其中user不分大小写

还可以直接改包

<!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.xxw.domain"></package> 替代<typeAlias>那个放在</typeAliases>里面

mappers标签的子标签:package

同理,这个mappers里的package

<mappers>
<!--xml配置映射文件-->
<!--<mapper resource="com/xxw/dao/IUserDao.xml"></mapper>-->
<!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了 -->
<package name="com.itheima.dao"></package>
</mappers>

但是弹幕说映射配置文件路径和名称一定要和java对上,不然报错;还有起别名容易导致日志乱码

 

添加上述三个标签后的SqlMapConfig.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
       可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
       resource属性: 常用的,短一些。。。
           用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
       url属性:
           是要求按照Url的写法来写地址
           URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
           它的写法:
               http://localhost:8080/mybatisserver/demo1Servlet
               协议      主机     端口       URI
           URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
   -->
    <!--<properties url="file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.properties">-->
    <properties resource="jdbcConfig.properties">
        <!-- <property name="driver" value="com.mysql.jdbc.Driver"></property>
         <property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"></property>
         <property name="username" value="root"></property>
         <property name="password" value="1234"></property>-->
    </properties>

    <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
    <typeAliases>
        <!--typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就再区分大小写 -->
        <!--<typeAlias type="com.xxw.domain.User" alias="user"></typeAlias>-->
        <!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
        <package name="com.itheima.domain"></package>
    </typeAliases>

    <!--这是mybatis的主配置文件-->
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql的环境-->
        <environment id="mysql">
            <!--配置事务类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--xml配置映射文件-->
        <!--<mapper resource="com/xxw/dao/IUserDao.xml"></mapper>-->
        <!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了 -->
            <package name="com.xxw.dao"></package>
    </mappers>
</configuration>
View Code

 

posted @ 2020-05-06 20:07  xinxinpang  阅读(154)  评论(0编辑  收藏  举报