03

03-27 1030阅读

文章目录

  • 入门案例
    • JDBC
    • Mybatis
    • Mybatis
      • Mybatis介绍
      • Mybatis的环境搭建
      • 动态代理
        • 增删改查示例
        • 事务
        • Mybatis的配置
          • properties
          • settings
          • typeAliases
          • environments
          • mappers
          • 输入映射
            • 一个参数
            • 多个参数
            • 按位置传值
            • 对象传值
            • 使用Map进行传值
            • #{}和${}的区别
            • 输出映射
              • 一个参数
              • 多个参数
              • 单个对象
              • 多个对象
              • resultMap

                入门案例

                JDBC

                public class UserDaoImpl implements UserDao{
                    @Override
                    public User selectByPrimaryKey(Integer id) throws Exception {
                        // 1.获得连接,如果后面需要提交事务,则执行connection.commit
                        Connection connection = JdbcUtil.getConnection();
                        // 2.预编译,预编译过程中传入了SQL语句
                        PreparedStatement preparedStatement = connection
                        .prepareStatement("select id, username, password, age, birthday
                        , create_date, mobile from cskaoyan_user where id = ?");
                        // 3.提供占位符位置的值
                        preparedStatement.setInt(1,id);
                        // 4.执行查询获得结果集
                        ResultSet resultSet = preparedStatement.executeQuery();
                        // 5.创建一个接收结果集中的值的实例
                        User user = new User();
                        while (resultSet.next()) {
                            // 6.获得结果集中的username列(column)中的值
                            String username = resultSet.getString("username");
                            //   获得结果集中的password列(column)中的值
                            String password = resultSet.getString("password");
                            int age = resultSet.getInt("age");
                            Date birthday = resultSet.getDate("birthday");
                            Date createDate = resultSet.getDate("create_date");
                            String mobile = resultSet.getString("mobile");
                            user.setId(id);
                            // 7.通过set方法封装给user实例中的username这个成员变量(property)
                            user.setUsername(username);
                            //   通过set方法封装给user实例中的password这个成员变量(property)
                            user.setPassword(password);
                            user.setAge(age);
                            user.setBirthday(birthday);
                            user.setCreateDate(createDate);
                            user.setMobile(mobile);
                        }
                        return user;
                    }
                }
                //定义了UserDao接口,我们传入id,可以查询user的记录出来
                public interface UserDao {
                    User selectByPrimaryKey(Integer id) throws Exception;
                }
                // 假如我们定义了实现类,那么我们可以这样子来调用获得user记录
                public class JdbcExecution {
                    // 查询id为2的用户
                    public static void main(String[] args) throws Exception{
                        UserDao userDao = new UserDaoImpl();
                        User user = userDao.selectByPrimaryKey(2);
                        System.out.println("user = " + user);
                    }
                }
                

                这个过程比较繁琐,并且存在着很多定制化的内容和耦合

                • SQL语句和代码直接耦合在一起
                • 设置参数过程比较繁琐,对应的关系只有占位符的序号,如果有多个占位符?的话,容易出错
                • 查询结果集的使用比较繁琐
                  • 手动调用构造方法来获得实例
                  • 要关注列名从结果集中取出数据
                  • 要关注列的类型手动调用不同的方法,比如getInt、getString、getDate
                  • 取出的值需要使用set方法来封装

                    Mybatis

                    • 导包
                              
                                  org.mybatis
                                  mybatis
                                  3.5.10
                              
                              
                                  mysql
                                  mysql-connector-java
                                  5.1.47
                              
                      
                      • 配置一个Mybatis的主配置文件,用来获取SqlSessionFactory
                        
                        
                            
                            
                                
                            
                            
                            
                                
                                    
                                    
                                        
                                        
                                        
                                        
                                    
                                
                            
                            
                                
                                
                            
                        
                        
                        • 配置一个专门用来存放SQL语句的配置文件Mapper.xml
                          
                          
                              
                              
                              
                              
                              
                              
                              
                              
                              
                              
                              
                              
                              
                                  select * from account where id = #{id}
                              
                              
                          
                          
                          • 实现
                            @Data
                            public class User {
                                Integer id;
                                String name;
                                Integer money;
                            }
                            public interface UserDao {
                                public User selectUserById(Integer id);
                            }
                            /**
                             * SqlSessionFactory:每一个Mybatis应用都是以SqlSessionFactory的实例对象为核心的。
                             * 使用Mybatis必须以SqlSessionFactory的实例为核心,再以SqlSessionFactory的实例生产SqlSession实例对象的。
                             *
                             * SqlSession:这个其实表示和数据库之间的一个连接,里面封装了 Connection对象
                             */
                            public class UserImpl implements UserDao{
                                @Override
                                public User selectUserById(Integer id){
                                    // 在映射文件中的编号:usersql.selectById
                                    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
                                    User user = null;
                                    try {
                                        InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
                                        SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
                                        // sql 会话,其实是对connection做了封装
                                        SqlSession sqlSession = sqlSessionFactory.openSession();
                                        // preparedStatement + setInt(1, id) + preparedStatement.executeQuery()
                                        // 然后将resultSet变成一个User实例
                                        user = sqlSession.selectOne("userSql.selectById", id);
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                    return user;
                                }
                            }
                            

                            在上面的案例中MyBatis做了什么事情:

                            • connection.preparedStatement需要传入的Sql语句,我们仅仅提供了坐标(映射文件的命名空间+id)
                            • 参数和占位符的对应关系,自动对应起来
                            • resultSet获得结果集,并且封装为User实例的过程完全是MyBatis自动完成的

                              Mybatis

                              Mybatis介绍

                              • Mybatis是一个基于Java的持久层框架
                              • Mybatis是一个ORM(Object Relationship Mapping)框架(对象关系映射框架)
                                • Mybatis就是一个可以帮助我们把关系型数据库中的记录转化为Java对象,把Java对象转化为关系型数据库中的记录的这么一个框架。
                                  • 类和表之间的关系(eg:User类和test_user表之间的关系)
                                  • 类中的成员变量和表中的列之间的关系(名称、JavaType和JdbcType)
                                  • 数据库中的一条记录和Java中的一个实例(比如一个user对象和test_user中的一条记录)
                                  • 它支持自定义 SQL、存储过程以及高级映射
                                    • Mybatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
                                    • Mybatis 可以通过简单的XML或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
                                    • Mybatis就是一个可以帮助我们在Java代码中更加高效的去操作数据库的一个框架

                                      Mybatis的环境搭建

                                      1. 导包在pom.xml中
                                        
                                        
                                              org.mybatis
                                              mybatis
                                              3.5.9
                                        
                                        
                                        
                                              mysql
                                              mysql-connector-java
                                              5.1.47
                                        
                                      
                                        
                                              junit
                                              junit
                                              4.12
                                        
                                      
                                      
                                      1. 配置MyBatis的主配置文件(mybatis-config.xml)
                                      
                                      
                                      
                                      
                                      
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      1. 创建一个Java接口Mapper接口文件 (注意路径)
                                      2. 创建一个与Java接口文件对应的Mapper.xml配置文件

                                      之后的步骤见上面的Mybatis的入门案例


                                      动态代理

                                      上面代码存在的一些不足:

                                      • 目前Mybatis使用起来还不够灵活,不够简单。
                                      • 虽然解决了SQL语句硬编码的问题,但是又出现了新的问题,SQL语句的坐标存在硬编码
                                      • sqlSession调用的方法需要我们自己去指定,也就是UserDaoImpl中的内容还不够通用,我们想要进一步干掉它

                                        而Mybatis的动态代理可以帮助我们去生成接口的代理对象,我们可以自己不实现接口。

                                        eg:

                                        public class MyBatisUtil {
                                            // 线程安全的值,可以全局共享
                                            private static SqlSessionFactory sqlSessionFactory;
                                            static {
                                                try {
                                                    sqlSessionFactory = new SqlSessionFactoryBuilder().
                                                            build(Resources.getResourceAsStream("mybatis.xml"));
                                                } catch (IOException e) {
                                                    e.printStackTrace();
                                                }
                                            }
                                            public static SqlSessionFactory getSqlSessionFactory() {
                                                return sqlSessionFactory;
                                            }
                                        }
                                        public class MybatisTest {
                                            @Test
                                            public void myTest() {
                                                // Mybatis生成的代理对象 -> 没有委托类 -> 只能从接口身上获得一些信息
                                                /**
                                                 * 获得接口的全限定类名
                                                 * 获得方法的数组 -> 方法的名称、返回值类型、参数的个数和类型
                                                 * 需要一个sql语句在映射文件中的坐标 -> 能否从上面选择一些信息保证组合起来的坐标是唯一的
                                                 * 坐标 = 接口的权限定类名 + 方法名(接口中的方法不允许重载)
                                                 */
                                                SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();
                                                SqlSession sqlSession = sqlSessionFactory.openSession();
                                                UserDao userDao = sqlSession.getMapper(UserDao.class);
                                                User user = userDao.selectUserById(2);
                                                System.out.println(user);
                                            }
                                        }
                                        
                                        
                                        
                                            
                                            
                                            
                                            
                                            
                                            
                                            
                                            
                                            
                                            
                                            
                                            
                                            
                                                /*不建议写select* */
                                                select id,name,money from account where id = #{id}
                                            
                                            
                                        
                                        

                                        增删改查示例

                                            
                                            
                                            
                                                insert into account(id, name, money) values (#{id}, #{name}, #{money});
                                            
                                            
                                                update account set name = #{name} where id = #{id};
                                            
                                            
                                                delete from account where id = #{id};
                                            
                                        

                                        对应接口:

                                        int insertUser(User user);
                                        int updateUser(String name, Integer id);
                                        int deleteById(Integer id);
                                        

                                        但是存在问题:Mybatis中openSession不提供事务的提交

                                        事务

                                        在使用Mybatis的时候, 自带事务,而且事务默认情况下是不会自动提交的

                                        • 解决方法一:执行完SQL语句之后, 使用sqlSession提交事务

                                          eg:sqlSession.commit();

                                        • 解决办法二: 执行完SQL语句之后, 使用sqlSession内部封装的Connection 提交事务

                                          eg:Connection conn = sqlSession.getConnection(); conn.commit();

                                        • 解决办法三(自动提交) :在获得SqlSession的时候,给sqlSessionFactory.openSession设置为真

                                          eg:SqlSession session = sqlSessionFactory.openSession(true);


                                          Mybatis的配置

                                          Mybatis的核心配置文件:

                                          (这些标签都是有序的,按下面排序)

                                          03

                                          properties

                                          properties表示可以外部配置的属性,并可以进行动态替换。(作为典型的是JDBC配置)

                                          eg:

                                          jdbc.properties文件中:
                                          driver=com.mysql.jdbc.Driver
                                          url=jdbc:mysql://localhost:3306/test_20240301?useSSL=false&userUnicode=true&characterEncoding=utf8
                                          username=root
                                          password=123456
                                          
                                          在Mybatis_config.xml中的内容为:
                                          
                                          
                                          
                                          
                                          .....
                                          
                                                 
                                                      
                                                      
                                                          
                                                          
                                                          
                                                          
                                                      
                                                  
                                          
                                          

                                          settings

                                          settings是MyBatis的行为配置(类似于idea和settings的关系)

                                          eg:

                                          日志的配置:

                                          
                                             
                                             
                                          	
                                          
                                          

                                          其它一些settings配置:

                                          // 缓存
                                          
                                          // 懒加载
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          
                                          

                                          typeAliases

                                          typeAlies类型别名。(也就是我们可以对 类 起别名,简化操作) (暂时不建议使用)

                                          eg:

                                           
                                           
                                               
                                               
                                               
                                           
                                          
                                          

                                          则在Mapper.xml中的使用为:

                                          // account == com.snow.www.bean.Account
                                           
                                           select * from account where id = #{id}
                                          
                                          

                                          environments

                                          environments:可以配置成适应多种环境。比如开发环境、测试环境和生产环境等可能需要有不同的配置。

                                          eg:

                                          
                                          
                                          
                                             
                                             
                                             
                                             
                                             
                                                 
                                                 
                                                 
                                                 
                                             
                                          
                                          
                                          

                                          mappers

                                          这个是映射器的配置。配置mapper.xml配置文件。

                                          • 配置方式一:直接以对应mapper文件的相对路径

                                            eg:

                                                
                                            
                                                 
                                                 
                                                 
                                             
                                            
                                            
                                            • 配置方式二:配置某个包下的所有的配置文件

                                              eg:

                                                 
                                              
                                              	
                                                      
                                                  
                                              
                                              

                                              输入映射

                                              • 输入映射其实就是在说Mybatis是如何传值的
                                              • 映射文件中的SQL语句中的语法:#{}里写什么东西,#{}这个位置最终在预编译的过程中变为了?
                                              • 在Mapper接口中,方法的形参写了什么样式(个数、类型、注解),最终在映射文件中该方法对应的sql语句中的#{}应该如何写

                                                一个参数

                                                一个参数:(基本类型、包装类、String)

                                                • #{任意值} 来取值: 不建议使用(显得不标准),建议使用注解写法
                                                  • 虽然一个参数的时候, 可以在{}内部任意书写参数名, 这种乱写行为不好, 不要这么写

                                                    eg:

                                                      select * from account where id = #{xxx}
                                                    
                                                    
                                                    • 如果在方法中 的一个参数加了@Param注解,那么 后面就只能通过 #{注解值} 来取值

                                                      eg:

                                                      // 查找
                                                      public Account selectAccountById2(@Param("id") Integer id);
                                                      
                                                        select * from account where id = #{id}
                                                      
                                                      

                                                      多个参数

                                                      多个参数:需要注解指明#{注解值} 来取值

                                                        1. 直接写多个值,用参数名简单匹配是不识别的
                                                        1. 如果参数名简单匹配是不识别,又不想加注解,也是有别的解决手段(按位传值: 不建议), 但是建议加注解(最标准的写法)

                                                        eg:

                                                        List selectListByIdOrName(@Param("id") Integer id,@Param("name") String name);
                                                        
                                                        select * from account where id = #{id} or name = #{name}
                                                        
                                                        

                                                        按位置传值

                                                        按位传值:完全不建议(容易因为程序员的记忆和修改导致bug产生, 除非除了按位传值没办法了)

                                                        • 方式一::arg0、arg1、arg2...
                                                          • 下标从0开始
                                                          • 方式二:param1、param2、param3...
                                                            • 下标从1开始

                                                              eg:

                                                              userMapper.insertUser("zs", 18, "beijing");
                                                              
                                                              方式一:
                                                              
                                                                 insert into `user`  set `name`=#{arg0}, age=#{arg1}, address=#{arg2}
                                                              
                                                              方式二:
                                                              
                                                                 insert into `user`  set `name`=#{param1}, age=#{param2}, address=#{param3}
                                                              
                                                              

                                                              对象传值

                                                              • 方式一:SQL使用的参数命名要和对象内部属性保持一致 (#{成员变量名} 来取值)

                                                                eg:

                                                                    // 对象传值,没有使用@Param注解,则是成员变量名
                                                                    int insert1(User user);
                                                                
                                                                    
                                                                        insert into account(id,name,money) values (#{id}, #{name} ,#{money})
                                                                    
                                                                
                                                                • 方式二:对象有注解,必须通过 #{注解值.成员变量名}来取值

                                                                  eg:

                                                                      // 对象传值,使用@Param注解,则是@Param写了什么就用什么
                                                                      // user.money....
                                                                      int insert2(@Param("user") User user);
                                                                  
                                                                      
                                                                         insert into account(id,name,money) values (#{user.id}, #{user.name}, #{user.money})
                                                                      
                                                                  

                                                                  使用Map进行传值

                                                                  • 方式一:SQL使用的参数命名要和Map中存储数据的key保持一致 (#{key}来取值)

                                                                    eg:

                                                                        // Map map = new HashMap();
                                                                        // map.put("id", 3);
                                                                        // map.put("name", "ss")
                                                                        // Map传值 --> 没有使用@Param注解 --> #{}里面写的是map的key:id和name
                                                                        int updateNameById(Map map);
                                                                    
                                                                        
                                                                            update account set name = #{name} where id = #{id}
                                                                        
                                                                    
                                                                    • 方式二:Map对象有注解, 必须通过#{注解值.key}来取值

                                                                      eg:

                                                                          // Map传值 --> 使用@Param注解 --> #{}里面写的是@Param注解的值 + map的key:map.id和map.name
                                                                          int updateNameById2(@Param("map") Map map);
                                                                      
                                                                          
                                                                              update account set name = #{map.name} where id = #{map.id}
                                                                          
                                                                      

                                                                      小结:

                                                                      输入映射,Mybatis如何使用的user,通过get方法来使用。


                                                                      #{}和${}的区别

                                                                      • 使用${}做的就是字符串的拼接,如果传入的是字符串,需要在${}外围手动增加单引号``
                                                                        • 核心点:使用${}有SQL注入的风险(SQL注入指:在执行的SQL语句之外额外执行一部分,导致信息泄露或者数据库被丢弃)
                                                                        • 使用#{}过程是预编译,不会有SQL注入的风险
                                                                        • #{参数}使用:预编译占位 (尽量使用 #{} ) PreparedStatement

                                                                          eg:

                                                                              
                                                                                  insert into account(id,name,money) values (#{id}, #{name} ,#{money})
                                                                              
                                                                          
                                                                          /**
                                                                           * ==>  Preparing: insert into account(id,name,money) values (?, ? ,?)
                                                                           * ==> Parameters: 6(Integer), ss(String), 8000(Integer)
                                                                           *   Preparing: insert into account(id,name,money) values (5, `ws` ,`7000`)
                                                                           */
                                                                          

                                                                          输出映射

                                                                          • 输出映射一定和查询有关系,一定对应的是select标签
                                                                          • 使用select标签一定使用和类型有关系的属性:
                                                                            • resultType
                                                                            • resultMap
                                                                            • resultType中可以写别名

                                                                              eg:

                                                                              -- 只有1列,并且记录数为1条  → 查询user表中有多少条记录
                                                                              -- 一个int或Integer类型的值来接收
                                                                              select count(*) from account ;
                                                                              -- 只有一列,结果的记录数为多条 → 查询年龄为xxx的用户的名称
                                                                              -- 数组或List、Set
                                                                              select name from account where age = 25;
                                                                              -- 多列,结果的记录数为1条 → 查询id为某个值的用户的全部信息
                                                                              -- 引用类型对象
                                                                              select id,name,money from account where id = 2;
                                                                              -- 多列,结果的记录数为多条 → 查询年龄为xxx的用户的全部信息
                                                                              -- 引用类型对象的数组或List、Set
                                                                              select id,name,money from account where age = 25 ;
                                                                              

                                                                              综上可得:

                                                                              • 选择何种封装类型:取决于结果集中的列的个数,以及结果的记录数
                                                                              • 封装最终体现在:落脚点在Mapper接口中的方法的返回值类型

                                                                                一个参数

                                                                                指的是:结果列为1且记录数为1(或0)

                                                                                • 一个参数: 必须要有resultType(写简单参数的全限定名称或者是内置的别名)

                                                                                  eg:

                                                                                      // 单个列,结果记录数为1
                                                                                      int selectCount();
                                                                                      String selectNameById(Integer id);
                                                                                  
                                                                                      
                                                                                          select count(*) from account;
                                                                                      
                                                                                      
                                                                                          select name from account where id = #{id};
                                                                                      
                                                                                  

                                                                                  多个参数

                                                                                  指的是:列只有一列,结果集中的记录数有多条(0或1条)

                                                                                  • 指: 多个参数构成的数组/List/Set
                                                                                  • 当我们返回多个简单参数的时候,在方法中定义的是数组就会返回数组,定义的是集合就会返回集合。
                                                                                    • xml中的标签配置不需要改变。并且, resultType的值是单个记录的类型

                                                                                      eg:

                                                                                          // 单个列,结果记录数为多条
                                                                                          // 按照不同的类型来封装,但是SQL语句是一样的
                                                                                          String[] selectNamesByMoney1(Integer money);
                                                                                          List selectNamesByMoney2(Integer money);
                                                                                          Set selectNamesByMoney3(Integer money);
                                                                                      
                                                                                          
                                                                                              select name from account where money = #{money};
                                                                                          
                                                                                          
                                                                                              select name from account where money = #{money};
                                                                                          
                                                                                          
                                                                                              select name from account where money = #{money};
                                                                                          
                                                                                      

                                                                                      单个对象

                                                                                      • 核心点:查询结果集中的列名 要和 对象中的成员变量名(set方法)相同
                                                                                      • 查询结果集中的列名可以通过as起别名的方式做修改

                                                                                        eg:

                                                                                                User selectAllMember(Integer id);
                                                                                                User user = userMapper.selectAllMember(2);
                                                                                        
                                                                                            
                                                                                                select * from account where id = #{id};
                                                                                            
                                                                                        

                                                                                        多个对象

                                                                                        • 多个对象:数组/List/Set
                                                                                        • resultType的值是单个元素的类型

                                                                                          JDBC的封装举例:

                                                                                          ResultSet resultSet = prepareStatement.executeQuery();
                                                                                          List users = new ArrayList();
                                                                                          while(resultSet.next()){
                                                                                            User user = new User();
                                                                                            user.setUsername(resultSet.getString("username"));
                                                                                            user.setPassword(resultSet.getString("password"));
                                                                                            users.add(user);
                                                                                          }
                                                                                          //如果你需要一个Set可以在第2行这里定义为一个set ,也可以将这个List转为一个Set
                                                                                          //如果你需要一个数组,也可以将这个List转为一个数组
                                                                                          

                                                                                          eg:

                                                                                          // 多个列,结果记录数为多条
                                                                                          User[] selectByAge1(@Param("age") Integer age);
                                                                                          List selectByAge2(@Param("age") Integer age);
                                                                                          Set selectByAge3(@Param("age") Integer age);
                                                                                          
                                                                                          select * from account
                                                                                          where age = #{age}
                                                                                          
                                                                                          
                                                                                          select * from account
                                                                                          where age = #{age}
                                                                                          
                                                                                          
                                                                                          select * from account
                                                                                          where age = #{age}
                                                                                          
                                                                                          

                                                                                          resultMap

                                                                                          • resultMap:是用来做参数映射的
                                                                                          • 存在这样的对应关系,我们才知道从结果集拿那一列的值(resultSet.getString("列名")),获得的值要封装给哪一个成员变量
                                                                                          • resultMap是可以复用的

                                                                                            eg:

                                                                                            UserVo selectUserVoByPrimaryKey(@Param("id") Integer id);
                                                                                            UserVo userVo = userMapper.selectUserVoByPrimaryKey(2);
                                                                                            System.out.println("userVo = " + userVo);
                                                                                            
                                                                                                
                                                                                                
                                                                                                
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                
                                                                                                
                                                                                                
                                                                                                    select * from account where id = #{id};
                                                                                                
                                                                                            

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]