首页 / 更多教程 / mybatis基础2
mybatis基础2
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了mybatis基础2,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含20431字,纯文字阅读大概需要30分钟。
内容图文
![mybatis基础2](/upload/InfoBanner/zyjiaocheng/1069/7d5d0e7e4b084d4e81a1067f509e4737.jpg)
1、输入与输出映射
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
1.1parameterType(输入类型)
1.1.1基本类型
1.1.2pojo类型
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称
1.1.3传递pojo包装对象
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件
(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo类中包含pojo。
QueryVo包装对象
public class QueryVo { private User user; public User getUser() { returnuser; } publicvoid setUser(User user) { this.user = user; } }
添加Mapper配置
<!-- 使用包装类型查询用户 使用ognl从对象中取属性值,如果是包装对象可以使用.操作符来取内容部的属性 --> < selectid ="findUserByQueryVo" parameterType ="queryvo" resultType ="user" > SELECT * FROM user where username like ‘%${user.username}%‘ </ select >
定义接口
List<User> findUserByQueryVo(QueryVo queryVo)
测试方法
@Test publicvoidtestFindUserByQueryVo() throws Exception { SqlSession sqlSession = sessionFactory.openSession(); //获得mapper的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //创建QueryVo对象 QueryVo queryVo = new QueryVo(); //创建user对象 User user = new User(); user.setUsername("刘"); queryVo.setUser(user); //根据queryvo查询用户 List<User> list = userMapper.findUserByQueryVo(queryVo); System.out.println(list); sqlSession.close(); }
1.2resultType(输出类型)
1.2.1输出基本类型
添加mapper配置
<!-- 只有返回一行一列的时候,那么返回值类型才可以是指定成基本类型 --> < select id ="findUserCount" resultType ="java.lang.Integer" > select count(*) from user </ select >
Mapper接口
public int findUserCount(User user) throws Exception;
测试:
Publicvoid testFindUserCount() throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获取mapper接口实例 UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User(); user.setUsername("管理员"); //传递Hashmap对象查询用户列表 intcount = userMapper.findUserCount(user); //关闭session session.close(); }
输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。
使用session的selectOne可查询单条记录。
1.2.2输出pojo类型
配置Mapper
< select id ="findUserByUserName" parameterType ="java.lang.String" resultType ="com.wang.pojo.User" > SELECT * from user where username like ‘%${value}%‘ </ select >
Mapper接口
public List<User> findUserByUserName(String name);
测试
@Test public void findUserByUserName() throws Exception{ SqlSession session = factory.openSession(); //通过getMapper实例化接口 UserMapper userMapper = session.getMapper(UserMapper.class); List<User> users= userMapper.findUserByUserName("王"); System.err.println(users); }
2、动态sql
通过mybatis提供的各种标签方法实现动态拼接sql。
2.1 if
<!-- 传递pojo综合查询用户信息 --> < selectid ="findUserList" parameterType ="user" resultType ="user" > select * from user where 1=1 < iftest ="id!=null" > and id=#{id} </ if > < iftest ="username!=null and username!=‘‘" > and username like ‘%${username}%‘ </ if > </ select >
注意要做不等于空字符串校验。
2.2 Where
< selectid ="findUserList" parameterType ="user" resultType ="user" > select * from user < where > < iftest ="id!=null and id!=‘‘" > and id=#{id} </ if > < iftest ="username!=null and username!=‘‘" > and username like ‘%${username}%‘ </ if > </ where > </ select >
where 标签作用:
1、会自动向sql中添加where关键字
2、会自动去掉第一个条件的and关键字
2.3 foreach
向sql传递数组或List,mybatis使用foreach解析,如下
在QueryVo中声明:
public class QueryVo { private List<Integer> ids;public List<Integer> getIds() { return ids; } publicvoid setIds(List<Integer> ids) { this.ids = ids; } }
测试:
@Test public void testfindUserByIds()throws Exception{ SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); QueryVo queryVo =new QueryVo(); List<Integer> integers = new ArrayList<>(); integers.add(1); integers.add(10); integers.add(31); queryVo.setIds(integers); List<User> users = mapper.findUserByIds(queryVo); System.out.println(users); }
对应的sql映射文件
< select id ="findUserByIds" parameterType ="com.wang.pojo.QueryVo" resultType ="com.wang.pojo.User" > select * from user < where > < if test ="ids !=null" > <!-- foreach:循环传入集合的参数 collection:传入的集合 item:每次循环将循环出的数据放入这个变量中 open:循环开始拼接的字符串 close:循环结束拼接的字符串 separator:循环中拼接分隔符 --> < foreach collection ="ids" item ="id" open ="id in (" close =") " separator ="," > #{id} </ foreach > </ if > </ where > </ select >
foreach:循环传入集合的参数 collection:传入的集合 item:每次循环将循环出的数据放入这个变量中 open:循环开始拼接的字符串 close:循环结束拼接的字符串 separator:循环中拼接分隔符
2.4sql片段
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,如下:
<!-- 封装sql条件,封装后可以重用 ID:是唯一表示 --> < sql id ="userWhere" > <!-- where 标签作用: 1、会自动向sql中添加where关键字 2、会自动去掉第一个条件的and关键字 --> < where > < if test ="username !=null and username !=‘‘" > and username like ‘%${username}%‘ </ if > < if test ="sex !=null and sex !=‘‘" > and sex =#{sex} </ if > </ where > </ sql >
引入sql片段:
< select id ="findUserByUserNameAndSex" parameterType ="com.wang.pojo.User" resultType ="com.wang.pojo.User" > select * from user < include refid ="userWhere" ></ include > </ select >
3、关联查询
两个表:
顾客表:
CREATE TABLE `user` ( `id` int(11) NOTNULL AUTO_INCREMENT, `username` varchar(32) NOTNULL COMMENT ‘用户名称‘, `birthday` date DEFAULTNULL COMMENT ‘生日‘, `sex` char(1) DEFAULTNULL COMMENT ‘性别‘, `address` varchar(256) DEFAULTNULL COMMENT ‘地址‘, PRIMARYKEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=32DEFAULT CHARSET=utf8;
订单表:
CREATE TABLE `orders` ( `id` int(11) NOTNULL AUTO_INCREMENT, `user_id` int(11) NOTNULL COMMENT ‘下单用户id‘, `number` varchar(32) NOTNULL COMMENT ‘订单号‘, `createtime` datetimeNOTNULL COMMENT ‘创建订单时间‘, `note` varchar(100) DEFAULTNULL COMMENT ‘备注‘, PRIMARYKEY (`id`), KEY `FK_orders_1` (`user_id`), CONSTRAINT `FK_orders_id` FOREIGNKEY (`user_id`) REFERENCES `user` (`id`) ONDELETE NO ACTION ONUPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=6DEFAULT CHARSET=utf8;
3.1一对一
对于两表:商品中订单与顾客的关系为一对一
对应的sql语句如下:
select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id= b.id
<!-- resultType返回的属性名与列命一直 --> < select id ="findOrdersAndUser1" resultType ="cn.itheima.pojo.CustomOrders" > select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id = b.id </ select >
3.1.1.解法一:自动自动映射
新键一个pojo让其继承Orders,之后在平铺User中所有的属性(决不可直接把user当做属性)
如下:
public class CustomOrders extends Orders{ //不能直接声明为userprivateint uid; //resultType返回的属性域列命一致,故为uid private String username;// 用户姓名private String sex;// 性别private Date birthday;// 生日private String address;// 地址publicint getUid() { return uid; } publicvoid setUid(int uid) { this.uid = uid; } public String getUsername() { return username; } publicvoid setUsername(String username) { this.username = username; } public String getSex() { return sex; } publicvoid setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } publicvoid setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } publicvoid setAddress(String address) { this.address = address; } }
接口:
public List<CustomOrders> findOrdersAndUser1();
测试:
@Test public void findOrdersAndUser1() throws Exception{ SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); List<CustomOrders> customOrders = mapper.findOrdersAndUser1(); System.err.println(customOrders); }
3.1.2手动映射
a、定义po类
在Orders类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; private User user; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserId() { return userId; } publicvoid setUserId(Integer userId) { this.userId = userId; } public String getNumber() { return number; } publicvoid setNumber(String number) { this.number = number == null ? null : number.trim(); } public Date getCreatetime() { return createtime; } publicvoid setCreatetime(Date createtime) { this.createtime = createtime; } public String getNote() { return note; } publicvoid setNote(String note) { this.note = note == null ? null : note.trim(); } public User getUser() { return user; } publicvoid setUser(User user) { this.user = user; } }
b、mapper.xml配置
<!-- id:resultMap唯一标识 type:将查询出的数据放入指定的对象中 注意:手动映射需要:指定数据库中表的字段名与java中pojo类的属性名称对应关系 --> <!-- 以Orders为主,查询数据放入其中,把User放入其中当做属性 --> < resultMap type ="com.wang.pojo.Orders" id ="orderAndUserResultMap" > <!-- id标签指定主键字段对应关系 column:列,数据库中字段名称 property:pojo中属性名 --> < id column ="id" property ="id" /> <!-- result指定非属性列的对应关系 --> < result column ="user_id" property ="userId" /> < result column ="number" property ="number" /> < result column ="createtime" property ="createtime" /> < result column ="note" property ="note" /> <!-- 指定单个对象的对应关系 property:指定将数据放入Oders中的user属性中 JavaType:支付user属性类型 --> < association property ="user" javaType ="com.wang.pojo.User" > < id column ="uid" property ="id" /> < result column ="username" property ="username" /> < result column ="sex" property ="sex" /> < result column ="birthday" property ="birthday" /> < result column ="address" property ="address" /> </ association > </ resultMap > < select id ="findOrdersAndUser2" resultMap ="orderAndUserResultMap" > select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id = b.id </ select >
新的方法:
resultMap标签:
id:resultMap唯一标识
type:将查询出的数据放入指定的对象中 注意:手动映射需要:指定数据库中表的字段名与java中pojo类的属性名称对应关系
以Orders为主,查询数据放入其中,把User放入其中当做属性
<id column="" property=""/> 指定id标签指定主键字段对应关系 column:列,数据库中字段名称 property:pojo中属性名
<result column="" property=""/> result指定非属性列的对应关系
<association property="user" javaType="com.wang.pojo.User">
指定单个对象的对应关系
property:指定将数据放入Oders中的user属性中
JavaType:支付user属性类型
<id column="uid" property="id"/>
<result column="username" property="username"/>
接口定义:
public List<Orders> findOrdersAndUser2();
测试:
@Test public void testFindOrdersAndUser2() throws Exception{ SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); List<Orders> customOrders = mapper.findOrdersAndUser2(); System.out.println(customOrders); }
3.2多对一:
顾客与订单是多对一:
select a.*,b.id oid,user_id,number,createtime fromuser a,orders b where a.id=b.user_id
以顾客为主,User新pojo(新的List<Orders> ordersList)
public class User { private int id; private String username;// 用户姓名private String sex;// 性别private Date birthday;// 生日private String address;// 地址private List<Orders> ordersList; publicint getId() { return id; } publicvoid setId(int id) { this.id = id; } public String getUsername() { return username; } publicvoid setUsername(String username) { this.username = username; } public String getSex() { return sex; } publicvoid setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } publicvoid setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } publicvoid setAddress(String address) { this.address = address; } public List<Orders> getOrdersList() { return ordersList; } publicvoid setOrdersList(List<Orders> ordersList) { this.ordersList = ordersList; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]"; } }
对应的sql映射:
< select id ="findUserAndOrders" resultMap ="userAndOrderResultMap" > select a.*,b.id oid,user_id,number,createtime from user a,orders b where a.id=b.user_id </ select >
mapper.xml配置
< resultMap type ="com.wang.pojo.User" id ="userAndOrderResultMap" > < id column =" id" property ="id" /> < result column ="username" property ="username" /> < result column ="sex" property ="sex" /> < result column ="birthday" property ="birthday" /> < result column ="address" property ="address" /> <!-- 指定对应的集合对象关系映射 property:将数据放入User对象中的ordersList中 ofType:指定ordersList的范型的类型 --> < collection property ="ordersList" ofType ="com.wang.pojo.Orders" > < id column ="oid" property ="id" /> < result column ="user_id" property ="userId" /> < result column ="number" property ="number" /> < result column ="createtime" property ="createtime" /> < result column ="note" property ="note" /> </ collection > </ resultMap > < select id ="findUserAndOrders" resultMap ="userAndOrderResultMap" > select a.*,b.id oid,user_id,number,createtime from user a,orders b where a.id=b.user_id </ select >
标签resultMap中collection指定对应的集合对象关系映射
接口定义:
public List<User> findUserAndOrders();
测试:
@Test public void testfindUserAndOrders() throws Exception{ SqlSession session = factory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); List<User> customOrders = mapper.findUserAndOrders(); System.out.println(customOrders); }
整个:UserMapper.xml
<? 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接口代理实现规则: 1、映射文件中namespace要等于接口的全路径名 2、映射文件中sql语句id要等于接口的方法名 3、映射文件中传入参数类型要等于接口方法的传入参数类型 4、映射文件中返回结果集类型要等于接口方法的返回值类型 --> < mapper namespace ="com.wang.mapper.UserMapper" > <!-- 封装sql条件,封装后可以重用 ID:是唯一表示 --> < sql id ="userWhere" > <!-- where 标签作用: 1、会自动向sql中添加where关键字 2、会自动去掉第一个条件的and关键字 --> < where > < if test ="username !=null and username !=‘‘" > and username like ‘%${username}%‘ </ if > < if test ="sex !=null and sex !=‘‘" > and sex =#{sex} </ if > </ where > </ sql > <!-- id:sql语句唯一表示 parameterType:指定传入参数类型,对应pojo属性的类型 resultType:返回结果类型 #{}占位符,起到站位的作用,如果传入的是基本类型(string、long、int、boolean、float等), 那么#{}中的变量名称可以是随意写,一般写属性 --> < select id ="findUserById" parameterType ="java.lang.Integer" resultType ="com.wang.pojo.User" > SELECT * from user WHERE id =#{id} </ select > <!-- 如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所映射的文件一个配置成集合范型的类型 ${}拼接符,字符串原样拼接,如果传入的是基本类型(string、long、int、boolean、float等), 那么%{}中的变量名称必须是value 注意:有sql注入的风险 --> < select id ="findUserByUserName" parameterType ="java.lang.String" resultType ="com.wang.pojo.User" > SELECT * from user where username like ‘%${value}%‘ </ select > <!-- #{}:如果传入的pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性..... 如果要返回数据库自增主键,使用SELECT LAST_INSERT_ID() --> < insert id ="insertUser" parameterType ="com.wang.pojo.User" > <!-- 执行SELECT LAST_INSERT_ID()数据库函数,返回自增主键 keyProperty:将返回的主键放入传入参数的Id中保存 order:当前函数相对于insert语句的执行顺序,在insert前是BEFORE之后是AFTER resultType:ID的类型,就是keyProperty中的类型 --> < selectKey keyProperty ="id" order ="AFTER" resultType ="java.lang.Integer" > SELECT LAST_INSERT_ID() </ selectKey > INSERT INTO user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </ insert > < delete id ="deleteUserById" parameterType ="java.lang.Integer" > delete from user where id=#{id} </ delete > < update id ="updateById" parameterType ="com.wang.pojo.User" > update user set username=#{username} where id=#{id} </ update > <!-- 只有返回一行一列的时候,那么返回值类型才可以是指定成基本类型 --> < select id ="findUserCount" resultType ="java.lang.Integer" > select count(*) from user </ select > < select id ="findUserByUserNameAndSex" parameterType ="com.wang.pojo.User" resultType ="com.wang.pojo.User" > select * from user < include refid ="userWhere" ></ include > </ select > < select id ="findUserByIds" parameterType ="com.wang.pojo.QueryVo" resultType ="com.wang.pojo.User" > select * from user < where > < if test ="ids !=null" > <!-- foreach:循环传入集合的参数 collection:传入的集合 item:每次循环将循环出的数据放入这个变量中 open:循环开始拼接的字符串 close:循环结束拼接的字符串 separator:循环中拼接分隔符 --> < foreach collection ="ids" item ="id" open ="id in (" close =") " separator ="," > #{id} </ foreach > </ if > </ where > </ select > <!-- 一对一:自动映射 --> <!-- resultType返回的属性名与列命一直 --> < select id ="findOrdersAndUser1" resultType ="cn.itheima.pojo.CustomOrders" > select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id = b.id </ select > <!-- 一对一:手动映射 --> <!-- id:resultMap唯一标识 type:将查询出的数据放入指定的对象中 注意:手动映射需要:指定数据库中表的字段名与java中pojo类的属性名称对应关系 --> <!-- 以Orders为主,查询数据放入其中,把User放入其中当做属性 --> < resultMap type ="com.wang.pojo.Orders" id ="orderAndUserResultMap" > <!-- id标签指定主键字段对应关系 column:列,数据库中字段名称 property:pojo中属性名 --> < id column ="id" property ="id" /> <!-- result指定非属性列的对应关系 --> < result column ="user_id" property ="userId" /> < result column ="number" property ="number" /> < result column ="createtime" property ="createtime" /> < result column ="note" property ="note" /> <!-- 指定单个对象的对应关系 property:指定将数据放入Oders中的user属性中 JavaType:支付user属性类型 --> < association property ="user" javaType ="com.wang.pojo.User" > < id column ="uid" property ="id" /> < result column ="username" property ="username" /> < result column ="sex" property ="sex" /> < result column ="birthday" property ="birthday" /> < result column ="address" property ="address" /> </ association > </ resultMap > < select id ="findOrdersAndUser2" resultMap ="orderAndUserResultMap" > select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id = b.id </ select > < resultMap type ="com.wang.pojo.User" id ="userAndOrderResultMap" > < id column =" id" property ="id" /> < result column ="username" property ="username" /> < result column ="sex" property ="sex" /> < result column ="birthday" property ="birthday" /> < result column ="address" property ="address" /> <!-- 指定对应的集合对象关系映射 property:将数据放入User对象中的ordersList中 ofType:指定ordersList的范型的类型 --> < collection property ="ordersList" ofType ="com.wang.pojo.Orders" > < id column ="oid" property ="id" /> < result column ="user_id" property ="userId" /> < result column ="number" property ="number" /> < result column ="createtime" property ="createtime" /> < result column ="note" property ="note" /> </ collection > </ resultMap > < select id ="findUserAndOrders" resultMap ="userAndOrderResultMap" > select a.*,b.id oid,user_id,number,createtime from user a,orders b where a.id=b.user_id </ select > </ mapper >
对应的UserMapper.java接口
package com.wang.mapper; import java.util.List; import cn.itheima.pojo.CustomOrders; import com.wang.pojo.Orders; import com.wang.pojo.QueryVo; import com.wang.pojo.User; public interface UserMapper { public com.wang.pojo.User findUserById(java.lang.Integer id); // 动态代理形式中如果返回结果集为list,那么mybatis会生成实现类的使用 // 会自动调用selectList方法 public List<User> findUserByUserName(String name); publicvoid insertUser(User user); public Integer findUserCount(); public List<User> findUserByUserNameAndSex(User user); public List<User> findUserByIds(QueryVo vo); public List<CustomOrders> findOrdersAndUser1(); public List<Orders> findOrdersAndUser2(); public List<User> findUserAndOrders(); }
总结:
1、Mybatis解决jdbc编程的问题
1、 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
2、 Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3、 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4、 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
2、mybatis与hibernate不同
Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。
原文:http://www.cnblogs.com/mswangblog/p/6659602.html
内容总结
以上是互联网集市为您收集整理的mybatis基础2全部内容,希望文章能够帮你解决mybatis基础2所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。