zoukankan      html  css  js  c++  java
  • mybatis基础(上)

    • 框架图

      • SqlSessionFactoryBuilder
        • 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
        • 将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSesssionFactoryBuilder
        • 在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可
      • SqlSessionFactory
        • 通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)
        • 将来mybatis和spring整合后,使用单例模式管理SqlSessionFactory
      • SqlSession
        • 是一个面向(程序员)接口
        • SqlSession中提供了多操作数据库的方法,如:selectOne(返回单个对象)、selectList(返回单个或多个对象)
        • SqlSession是线程不安全的,在SqlSession实现类中除了有接口中的方法(操作数据库的方法),还有数据域属性
        • SqlSession最佳应用场合在方法体内,定义成局部变量使用。
    • 基础工程结构

      

    • 在db.properties的内容
      • # Create a file called log4j.properties as shown below and place it in your classpath:
        # 创建一个名为log4j.properties的文件,如下所示,并将其放在类路径中:
        # Global logging configuration
        # 在开发环境下日志级别要设置成DEBUG,生产环境设置成info或error
        log4j.rootLogger=DEBUG, stdout
        # MyBatis logging configuration...
        log4j.logger.org.mybatis.example.BlogMapper=TRACE
        # Console output...
        log4j.appender.stdout=org.apache.log4j.ConsoleAppender
        log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
        log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    • 在SqlMapConfig.xml的内容
      • <?xml version="1.0" encoding="UTF-8" ?>
        <!-- 配置XML文件包含MyBatis系统核心的设置,包括用于获取数据库连接实例的DataSource,
            以及用于确定如何确定事务范围和控制事务的TransactionManager。 -->
        <!-- 请注意验证XML文档所需的XML标头。 environment元素的主体包含事务管理和连接池的环境配置。
            mappers元素包含一个映射器列表 - 包含SQL代码和映射定义的XML文件和/或带注释的Java接口类。-->
        <!-- 与spring整合后environments配置将废除 -->
        <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">
        <configuration>
            <environments default="development">
                <environment id="development">
                    <!-- 使用jdbc事务管理,事务控制由mybatis -->
                    <transactionManager type="JDBC"/>
                    <!-- 数据库连接池,由mybatis管理 -->
                    <dataSource type="POOLED">
                        <property name="driver" value="com.mysql.jdbc.Driver"/>
                        <property name="url" value="jdbc://mysql://localhost:3306/[数据库名]?characterEncoding=utf-8"/>
                        <property name="username" value="[账号]"/>
                        <property name="password" value="[密码]"/>
                    </dataSource>
                </environment>
            </environments>
            <!-- 加载映射文件 -->
            <mappers>
                <mapper resource="sqlmap/User.xml"/>
            </mappers>
        </configuration>

    •  方法一
      • #db.properties
        #将数据库连接参数只配置在db.properties中(原因:方便对参数进行统一管理)
        jdbc.driver=com.mysql.jdbc.Driver
        jdbc.url=jdbc:mysql://localhost:3306/travelling_guideling?characterEncoding=utf-8
        jdbc.username=root
        jdbc.password=root
        
        
        
        <?xml version="1.0" encoding="UTF-8" ?>
        <!-- 配置XML文件包含MyBatis系统核心的设置,包括用于获取数据库连接实例的DataSource,
            以及用于确定如何确定事务范围和控制事务的TransactionManager。 -->
        <!-- 请注意验证XML文档所需的XML标头。 environment元素的主体包含事务管理和连接池的环境配置。
            mappers元素包含一个映射器列表 - 包含SQL代码和映射定义的XML文件和/或带注释的Java接口类。-->
        <!-- 与spring整合后environments配置将废除 -->
        <!--
            mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:
            properties(属性)、settings(全局配置参数)、typeAliases(类型别名)、typeHandlers(类型处理器)、
            objectFactory(对象工厂)、plugins(插件)、environments(环境集合属性对象)、environment(环境子属性对象)、
            transactionManager(事务管理)、dataSource(数据源)、mappers(映射器)
        -->
        <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">
        <configuration>
            <properties resource="db.properties"></properties>
        
            <!-- 别名定义 -->
            <typeAliases>
                <!--
                    针对单个别名定义
                    type:类型的路径
                    alias:别名
                -->
                <typeAlias type="cn.muriel.mybatis.po.User" alias="user"/>
                <!--
                    批量别名定义
                    指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大小写都可以)
                 -->
                <!--<package name="cn.muriel.mybatis.po"/>-->
            </typeAliases>
            <environments default="development">
                <environment id="development">
                    <!-- 使用jdbc事务管理,事务控制由mybatis -->
                    <transactionManager type="JDBC"/>
                    <!-- 数据库连接池,由mybatis管理 -->
                    <dataSource type="POOLED">
                        <!-- ${jdbc.driver}写成${jdbc.Driver},报错  -->
                        <property name="driver" value="${jdbc.driver}"/>
                        <property name="url" value="${jdbc.url}"/>
                        <property name="username" value="${jdbc.username}"/>
                        <property name="password" value="${jdbc.password}"/>
                    </dataSource>
                </environment>
            </environments>
            <!-- 加载映射文件 -->
            <mappers>
                <!-- 通过resource方法一次加载一个映射文件 -->
                <mapper resource="mapper/UserMapper.xml"/>
                <mapper resource="sqlmap/User.xml"/>
                <!-- 使用完全限定路径加载 -->
                <!--<mapper url="file:///"/>-->
                <!-- 使用mapper接口类路径 -->
                <!--
                       遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                                   上边规范的前提是:使用的是mapper代理方法
                 -->
                <!--<mapper class=""/>-->
                <!-- 使用批量加载mapper -->
                <!--
                     指定mapper接口的报名,mybatis自动扫描包下边的mapper接口进行加载
                     遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                                 上边规范的前提是:使用的是mapper代理方法
                -->
                <!-- <package name=""/> -->
            </mappers>
        </configuration>
        
        <?xml version="1.0" encoding="UTF-8" ?>
        <!-- 此时您可能想知道SqlSession或Mapper类究竟执行了什么。
            MyBatis提供的全套功能可以通过使用多年来MyBatis流行的基于XML的映射语言来实现。
            如果您以前使用过MyBatis,那么您将很熟悉这个概念,但是对XML映射文档进行了大量改进,以后会很清楚。 -->
        <!DOCTYPE mapper
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <!-- namespace命名空间。作用对sql进行分类化管理,理解sql隔离
             注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
        <mapper namespace="user">
             <select id="selectAllUser" resultType="cn.muriel.mybatis.po.User">
                select * from user
            </select>
        </mapper>
        
        
        
        /**
         * mybatis是一个持久层的框架
         */
        public class JDBCUtils {
        
            public SqlSession connection() throws IOException {
        
        
                //mybatis配置文件
                String path = "SqlMapConfig.xml";
                //得到配置文件流
        
                InputStream inputStream = null;
                SqlSession sqlSession = null;
                inputStream = Resources.getResourceAsStream(path);
        
        
                //创建会话工厂,传入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                //通过工厂得到SqlSession
                sqlSession = sqlSessionFactory.openSession();
        
                return sqlSession;
        
            }
        }
        
        
        
        public abstract class UserDao extends JDBCUtils {
        
        
            public abstract List<User> selectAllUser();
        
           
        }
        
        
        
        /**
         * UserDao的实现类
         */
        public class UserDaoImpl extends UserDao {
        
            @Override
            public List<User> selectAllUser() {
                try {
                    SqlSession connection = connection();
                    List<User> users = connection.selectList("user.selectAllUser");
        
                    return users;
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        
         
        }
        
        /**
         * 测试类
         */
        public class TestUtil {
        
            public static void main(String[] args) {
              
        
                UserDao userDao = new UserDaoImpl();
                JSONArray jsonArray = JSONArray.fromObject(userDao.selectAllUser());
                System.out.println(jsonArray + "");
        
             
        
            }
        }
    •  方法二
      • #db.properties
        #将数据库连接参数只配置在db.properties中(原因:方便对参数进行统一管理)
        jdbc.driver=com.mysql.jdbc.Driver
        jdbc.url=jdbc:mysql://localhost:3306/travelling_guideling?characterEncoding=utf-8
        jdbc.username=root
        jdbc.password=root
        
        
        
        <?xml version="1.0" encoding="UTF-8" ?>
        <!-- 配置XML文件包含MyBatis系统核心的设置,包括用于获取数据库连接实例的DataSource,
            以及用于确定如何确定事务范围和控制事务的TransactionManager。 -->
        <!-- 请注意验证XML文档所需的XML标头。 environment元素的主体包含事务管理和连接池的环境配置。
            mappers元素包含一个映射器列表 - 包含SQL代码和映射定义的XML文件和/或带注释的Java接口类。-->
        <!-- 与spring整合后environments配置将废除 -->
        <!--
            mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:
            properties(属性)、settings(全局配置参数)、typeAliases(类型别名)、typeHandlers(类型处理器)、
            objectFactory(对象工厂)、plugins(插件)、environments(环境集合属性对象)、environment(环境子属性对象)、
            transactionManager(事务管理)、dataSource(数据源)、mappers(映射器)
        -->
        <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">
        <configuration>
            <properties resource="db.properties"></properties>
        
            <!-- 别名定义 -->
            <typeAliases>
                <!--
                    针对单个别名定义
                    type:类型的路径
                    alias:别名
                -->
                <typeAlias type="cn.muriel.mybatis.po.User" alias="user"/>
                <!--
                    批量别名定义
                    指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大小写都可以)
                 -->
                <!--<package name="cn.muriel.mybatis.po"/>-->
            </typeAliases>
            <environments default="development">
                <environment id="development">
                    <!-- 使用jdbc事务管理,事务控制由mybatis -->
                    <transactionManager type="JDBC"/>
                    <!-- 数据库连接池,由mybatis管理 -->
                    <dataSource type="POOLED">
                        <!-- ${jdbc.driver}写成${jdbc.Driver},报错  -->
                        <property name="driver" value="${jdbc.driver}"/>
                        <property name="url" value="${jdbc.url}"/>
                        <property name="username" value="${jdbc.username}"/>
                        <property name="password" value="${jdbc.password}"/>
                    </dataSource>
                </environment>
            </environments>
            <!-- 加载映射文件 -->
            <mappers>
                <!-- 通过resource方法一次加载一个映射文件 -->
                <mapper resource="mapper/UserMapper.xml"/>
                <mapper resource="sqlmap/User.xml"/>
                <!-- 使用完全限定路径加载 -->
                <!--<mapper url="file:///"/>-->
                <!-- 使用mapper接口类路径 -->
                <!--
                       遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                                   上边规范的前提是:使用的是mapper代理方法
                 -->
                <!--<mapper class=""/>-->
                <!-- 使用批量加载mapper -->
                <!--
                     指定mapper接口的报名,mybatis自动扫描包下边的mapper接口进行加载
                     遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                                 上边规范的前提是:使用的是mapper代理方法
                -->
                <!-- <package name=""/> -->
            </mappers>
        </configuration>
        
        <?xml version="1.0" encoding="UTF-8" ?>
        <!-- 此时您可能想知道SqlSession或Mapper类究竟执行了什么。
            MyBatis提供的全套功能可以通过使用多年来MyBatis流行的基于XML的映射语言来实现。
            如果您以前使用过MyBatis,那么您将很熟悉这个概念,但是对XML映射文档进行了大量改进,以后会很清楚。 -->
        <!DOCTYPE mapper
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <!-- namespace命名空间。作用对sql进行分类化管理,理解sql隔离
             注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
        <mapper namespace="user">
              
            <!-- 通过OGNL(Object-Graph-Navigation-Language)方式来进行获取 -->
            <select id="selectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo"
                    resultType="cn.muriel.mybatis.po.UserCustom">
                select * from user where id = #{userCustom.id}
            </select>
        
        </mapper>
        
        
        
        /**
         * mybatis是一个持久层的框架
         */
        public class JDBCUtils {
        
            public SqlSession connection() throws IOException {
        
        
                //mybatis配置文件
                String path = "SqlMapConfig.xml";
                //得到配置文件流
        
                InputStream inputStream = null;
                SqlSession sqlSession = null;
                inputStream = Resources.getResourceAsStream(path);
        
        
                //创建会话工厂,传入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                //通过工厂得到SqlSession
                sqlSession = sqlSessionFactory.openSession();
        
                return sqlSession;
        
            }
        }
        
        
        
        /**
         * mapper.java接口中的方法名和mapper.xml中的statement的id一致
         * mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
         * mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致
         *
         *  系统框架中,dao层的代码是被业务处公用的
         *  即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求
         *  注意:持久层方法的参数可以包装类型、map、service方法中建议不要使用包装类型
         *
         * 【使用mapper.java的时候 必须是public interface UserMapper,
         * 若不小心写成Type class cn.muriel.mybatis.mapper.UserMapper is not known to the MapperRegistry.】
         */
        public  interface UserMapper {
        
            public List selectAllUser();
        
            public User selectUser(int id) throws Exception;
        }
        
        /**
         * 测试类
         */
        public class TestUtil {
        
            public static void main(String[] args) {
              
           JDBCUtils jdbcUtils = new JDBCUtils();
        
        
        
                try {
                    SqlSession sqlSession = jdbcUtils.connection();
                    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                    JSONArray sendJson = JSONArray.fromObject(mapper.selectUser(4));
                    System.out.println(sendJson + "");
        
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
        
             
        
            }
        }
    • ResultType和ResultMap的区别
      •  <!--
                定义resultMap:
                id:对resultMap的唯一标识
                type:reusltMap最终映射的java对象类型,可以使用别名
            -->
        
            <resultMap id="userResultMap" type="cn.muriel.mybatis.po.User">
                <!--
                    id标识查询结果集中唯一标识
                    column:查询出来的列名
                    property:type指定的pojo类型中的属性名
                    最终resultMap对column和property作一个映射关系(对应关系)
                 -->
                <id column="id_" property="id"/>
                <!--
                    result:对普通名映射定义
                    column:查询出来对列名
                    property:type指定对pojo类型中对属性名
                    最终resultMap对column和property做一个映射关系(对应关系)
                -->
                <result column="username_" property="username"/>
            </resultMap>
        
        
        <!--
                (resultType和resultMap的区别)
                resultType:使用resultType进行输出映射,只有查询出来的列名和Pojo中的属性名一致,该列才可以映射成功
                            不管是输出的pojp单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的
                            在mapper.java指定的方法返回值类型不一样:
                            (1)输出单个pojo对象,方法返回值是单个对象类型
                            (2)输出list的pojo对象,方法返回值是List<pojo>
                resultMap:如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射关系
                          (1)定义resultMap
                          (2)使用resultMap作为statement的输出映射类型
             -->
            <!-- 通过OGNL(Object-Graph-Navigation-Language)方式来进行获取 -->
              <select id="selectUser" parameterType="id" resultMap="userResultMap"
                    resultType="cn.muriel.mybatis.po.UserCustom">
                select id id_,username username username_ from user where id = #{userCustom.id}
            </select>
    • 什么是动态sql
      • mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼装、组接。
      • if判断
        •  <!-- 模糊查询用户 -->
              <!-- 若resultType写成resultMap 抛异常Result Maps collection does not contain value for XXX -->
              <select id="blurrySelectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo" resultType="cn.muriel.mybatis.po.UserCustom">
                  SELECT * from USER
                  <!-- where 可以自动去掉条件中第一个and -->
                  <where>
                      <if test="userCustom != null">
                          <if test="userCustom.root  != null">
                              and root = #{userCustom.root}
                          </if>
                          <if test="userCustom.username != null and userCustom.username != ''">
                              and username LIKE '%${userCustom.username}%'
                          </if>
          
          
                      </if>
                  </where>
              </select>
          
          
          public interface UserMapper {
          
              
               public List blurrySelectUser(UserQueryVo userQueryVo) throws Exception;
          }
          
          
          
          public class TestUtil {
          
              public static void main(String[] args) {
          
          
                  JDBCUtils jdbcUtils = new JDBCUtils();
                  try {
                      SqlSession sqlSession = jdbcUtils.connection();
                      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                      UserQueryVo userQueryVo = new UserQueryVo();
                      UserCustom user = new UserCustom();
                      user.setUsername("a");
                      user.setRoot(1);
                      userQueryVo.setUserCustom(user);
                      JSONArray sendJson = JSONArray.fromObject(mapper.blurrySelectUser(userQueryVo));
                      System.out.println(sendJson + "");
          
                  } catch (IOException e) {
                      e.printStackTrace();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
          
          
              }
          }
      • sql片段
        •  <!--
                  定义sql片段:
                      是基于单表来定义sql片段,这样的话这个sql片段可重用性才高
                      在sql片段中不要包括where
               -->
              <sql id="blurry_select_user_where">
                  <if test="userCustom != null">
                      <if test="userCustom.root  != null">
                          and root = #{userCustom.root}
                      </if>
                      <if test="userCustom.username != null and userCustom.username != ''">
                          and username LIKE '%${userCustom.username}%'
                      </if>
          
          
                  </if>
              </sql>  
          
          
          
          <!-- 模糊查询用户 -->
              <!-- 若resultType写成resultMap 抛异常Result Maps collection does not contain value for XXX -->
              <select id="blurrySelectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo" resultType="cn.muriel.mybatis.po.UserCustom">
                  SELECT * from USER
                  <!-- where 可以自动去掉条件中第一个and -->
                  <where>
                      <!-- 引用sql片段的id,如果refid指定的Id不再当前mapper文件中,需要在前边加namespace -->
                      <include refid="blurry_select_user_where"></include>
                      <!-- 在这里还可以引用其它的sql片段 -->
                  </where>
              </select>
          
             
      • foreach
        • public class UserQueryVo {
          
              private List<Integer> ids;
          
               //用户查询条件
              private UserCustom userCustom;
          
              public UserCustom getUserCustom() {
                  return userCustom;
              }
          
              public void setUserCustom(UserCustom userCustom) {
                  this.userCustom = userCustom;
              }
          
              public List<Integer> getIds() {
                  return ids;
              }
          
              public void setIds(List<Integer> ids) {
                  this.ids = ids;
              }
          }
          
          
          public interface UserMapper {
          
              public List blurrySelectUser(UserQueryVo userQueryVo) throws Exception;
          }
          
          
          
          <select id="blurrySelectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo"
                      resultType="cn.muriel.mybatis.po.UserCustom">
                  SELECT * from USER
                  <!-- where 可以自动去掉条件中第一个and -->
                  <where>
                      <!-- 引用sql片段的id,如果refid指定的Id不再当前mapper文件中,需要在前边加namespace -->
                      <include refid="blurry_select_user_where"></include>
                      <!-- 在这里还可以引用其它的sql片段 -->
                  </where>
              </select>
          
              <!--
                  定义sql片段:
                      是基于单表来定义sql片段,这样的话这个sql片段可重用性才高
                      在sql片段中不要包括where
               -->
              <sql id="blurry_select_user_where">
                  <if test="userCustom != null">
                      <if test="userCustom.root  != null">
                          and root = #{userCustom.root}
                      </if>
                      <if test="userCustom.username != null and userCustom.username != ''">
                          and username LIKE '%${userCustom.username}%'
                      </if>
          
          
                  </if>
                  <!--
                     collection:指定输入对象中属性集合
                     item:每个遍历生成对象中
                     open:开始遍历时拼接的串
                     close:结束遍历时拼接的串
                     spearator:遍历时两个对象中需要拼接的串
                   (SQL语句格式:AND (id=1 or id=2 or id =3))=3))
                  -->
                  <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
                      <!-- 每个遍历需要拼接的串 -->
                      id = #{user_id}
                  </foreach>
              </sql>
          
          
          
          
          public class TestUtil {
          
              public static void main(String[] args) {
          
          
                  JDBCUtils jdbcUtils = new JDBCUtils();
                  try {
                      SqlSession sqlSession = jdbcUtils.connection();
                      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                      UserQueryVo userQueryVo = new UserQueryVo();
                      UserCustom user = new UserCustom();
                      user.setUsername("a");
                      user.setRoot(1);
                      List list = new ArrayList();
                      list.add(1);
                      list.add(2);
                      list.add(3);
                      list.add(4);
                      list.add(5);
          
                      userQueryVo.setIds(list);
                      userQueryVo.setUserCustom(user);
                      JSONArray sendJson = JSONArray.fromObject(mapper.blurrySelectUser(userQueryVo));
                      System.out.println(sendJson + "");
          
                  } catch (IOException e) {
                      e.printStackTrace();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
          
          
              }
          }
        •    <!--
                     collection:指定输入对象中属性集合
                     item:每个遍历生成对象中
                     open:开始遍历时拼接的串
                     close:结束遍历时拼接的串
                     spearator:遍历时两个对象中需要拼接的串
                     (SQL语句格式:AND id in (1 , 2 ,3))
                  -->
                  <foreach collection="ids" item="user_id" open="and id IN (" close=")" separator=",">
                      <!-- 每个遍历需要拼接的串 -->
                      #{user_id}
                  </foreach>
  • 相关阅读:
    排序预处理的思想
    枚举
    math细节
    physics 衍射和ganshe
    hearing speaking words
    appium的环境安装
    基于ASP.NET MVC 4.0的音乐商店全套项目教程
    WPF/WinForm 关于窗体大小变化的消息机制处理
    用WPF搭建自己的万能播放器(C#)前篇
    VS2010网站发布到服务器上
  • 原文地址:https://www.cnblogs.com/fatRabbit-/p/10502484.html
Copyright © 2011-2022 走看看