MyBatis
1. java项目的基本三层架构
2. 框架和库的区别
-
框架: 是一整套技术解决方案
-
库:是对原有技术的封装 让操作更加简单而已
3.Mybatis的介绍
-
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github,通俗说法Ibatis3 = MyBatis
-
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
-
MyBatis是一个数据持久层(ORM)框架。把实体类和SQL语句之间建立了映射关系,是一种半自动化的ORM实现
-
MyBatis的优点:
-
减少代码量
-
基于SQL语法,简单易学
-
能了解底层组装过程
-
SQL语句封装在配置文件中,便于统一管理与维护,降低了程序的耦合度
-
程序调试方便
4. MyBatis的获取
-
第一种方式 从官网(也是跳转到github)
-
第二种方式 github
5. mybatis的目录介绍
6. Mybatis操作数据库
6.1. 环境搭建
6.1.1. 建库建表
create database mybatis; use mybatis; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(32) NOT NULL COMMENT '用户名称', `birthday` date DEFAULT NULL COMMENT '生日', `sex` char(1) DEFAULT NULL COMMENT '性别', `address` varchar(256) DEFAULT NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
6.1.2. 插入数据
insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'盛世名',NULL,'2',NULL), (10,'张甲吉','2014-07-10','1','北京市'),(16,'张吉东',NULL,'1','河南郑州'), (22,'孙训',NULL,'1','河南郑州'),(24,'周芷若',NULL,'1','河南郑州'), (25,'赵敏',NULL,'1','河南郑州'),(26,'小昭',NULL,NULL,NULL);
6.1.3. 创建java项目
6.1.4. 导入jar包(新建lib)
导入mybatis和mybatis的依赖包
导入mysql的驱动包
注意: 直接导入mybatis 和 mysql驱动包 2个包就可以了 但是建议把所有的包都导入进去
6.1.5. 创建实体类
package com.shangma.cn.entity; import java.util.Date; public class User { private int id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", sex='" + sex + '\'' + ", birthday=" + birthday + ", address='" + address + '\'' + '}'; } }
6.1.6. 编写主配置文件
<?xml version="1.0" encoding="UTF-8"?> <!--mybaits全局配置文件的约束--> <!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"/> <!--数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="rootroot"/> </dataSource> </environment> </environments> <mappers> <!--<mapper resource="org/mybatis/example/BlogMapper.xml"/>--> </mappers> </configuration>
6.1.7. 编写Mapper映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace=""> </mapper>
6.1.8. 基本目录结构如下
6.2. 增删改查
6.2.1. 根据id查询
6.2.1.1. 修改映射文件
<?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"> <!-- 添加的内容如下 --> <!-- namespace 表示命名空间 对sql的操作进行分类化管理 有点类似包管理 --> <mapper namespace="huige"> <!--是根据id查询用户 select标签表示查询 id属性: 要求在一个namespace当中唯一 id随意写 但是要唯一 parameterType表示参数的java类型 resultType 表示查询后的返回值java类型 #{id} 表示占位符 传过来是什么 id就等于什么 如果是基本数据类型 这个id可以随意写 --> <select id="findUserById" parameterType="int" resultType="com.shangma.cn.entity.User"> select * from user where id=#{id} </select> </mapper>
6.2.1.2. 修改配置文件
在 mappers标签中添加如下内容
<mappers> <!--mapper映射文件 resource 表示从src 下(也就是类路径下 开始找mapper.xml文件夹的路径,使用的是文件夹路径的形式“/”而不是“.”)--> <mapper resource="com/sm/qy30/mapper/userMapper.xml"/> </mappers>
6.2.1.3. 编写代码
public class TestDemo { /** * 通过id 查询 */ @Test public void selectById() throws IOException { //配置文件路径 String resource = "mybatis.xml"; //通过路径加载配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); //获得sqlsessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获得sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 操作数据库 User o = sqlSession.selectOne("huige.findUserById", 10); //打印结果 System.out.println(o); //关闭资源 sqlSession.close(); } }
6.2.1.4. 结果打印
6.2.1.5. 警告说明
6.2.2. 添加用户
6.2.2.1. 修改映射文件
<!-- 添加用户 参数类型 是引用类型 则 #{}中的值 不能胡写 要对应成 实体类中的属性名 --> <insert id="addUser" parameterType="com.shangma.cn.entity.User"> insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert>
6.2.2.2. 加载映射文件
已经加载过
6.2.2.3. 编写代码
@Test public void addUser() throws IOException { String path = "mybatis.xml"; InputStream in = Resources.getResourceAsStream(path); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); SqlSession sqlSession = factory.openSession(); User user = new User(); user.setUsername("辉哥"); user.setAddress("863中部软件园"); user.setBirthday(new Date()); user.setSex("男"); sqlSession.insert("huige.addUser",user); //要提交事务 不提交事务 则可能没有真正的持久化硬盘中 sqlSession.commit(); sqlSession.close(); }
6.2.3. 修改用户
6.2.3.1. 修改映射文件
<!-- 修改用户 --> <update id="updateUser" parameterType="com.shangma.cn.entity.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update>
6.2.3.2. 加载映射文件
已经加载过
6.2.3.3. 编写代码
@Test public void updateUser() throws IOException { String path = "mybatis.xml"; InputStream resourceAsStream = Resources.getResourceAsStream(path); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); //先查出来 再修改 User o = sqlSession.selectOne("huige.findUserById", 10); o.setAddress("尚马教育"); o.setSex("女"); sqlSession.update("huige.updateUser",o); sqlSession.commit(); sqlSession.close(); }
6.2.4. 删除用户
6.2.4.1. 修改映射文件
<!--删除用户--> <delete id="deleteUser" parameterType="int"> delete from user where id = #{id} </delete>
6.2.4.2. 加载映射文件
加载过了
6.2.4.3. 编写代码
@Test public void deleteUser() throws IOException { String path = "mybatis.xml"; InputStream resourceAsStream = Resources.getResourceAsStream(path); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.delete("huige.deleteUser",10); //只要不是查询 赠删改 都需要提交事务 sqlSession.commit(); sqlSession.close(); }
6.2.5. 模糊查询
6.2.5.1. 修改映射文件
<!--模糊查询 ${} 如果参数为简单类型时,${}里面的参数名称必须为value --> <select id="searchUser" parameterType="string" resultType="com.shangma.cn.entity.User"> select * from user where username like '%${value}%' </select>
6.2.5.2. 加载映射文件
加载过了
6.2.5.3. 编写代码
@Test public void searchUser() throws IOException { String path = "mybatis.xml"; InputStream resourceAsStream = Resources.getResourceAsStream(path); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> users = sqlSession.selectList("huige.searchUser", "小"); users.forEach(user -> System.out.println(user)); sqlSession.close(); }
6.2.6. 添加用户返回主键
6.2.6.1. 修改映射文件
<!-- 添加用户 参数类型 是引用类型 则 #{}中的值 不能胡写 要对应成 实体类中的属性名 --> <insert id="addUser" parameterType="com.shangma.cn.entity.User"> <!-- keyProperty 表示主键的属性 order 表示返回的主键是在添加前 还是添加后 取值after before resultType 表示返回值类型 last_insert_id() 是mysql中的函数 返回的是最后一次添加的id --> <selectKey keyProperty="id" order="AFTER" resultType="int"> select last_insert_id() </selectKey> insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert>
7. 面临的问题
-
问题一:代码中 存在大量的重复代码
-
问题二:我们mybatis是持久层框架属于dao的部分
生命周期介绍
8. 简单的封装
/** * 对重复的代码进行简单封装 */ public class TestDemo2 { SqlSessionFactory sqlSessionFactory; SqlSession sqlSession; InputStream inputStream; @Before public void init() throws IOException { System.out.println("init方法打印了"); //配置文件路径 String resource = "mybatis.xml"; //通过路径加载配置文件 inputStream = Resources.getResourceAsStream(resource); //获得sqlsessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); } /** * 通过id 查询 */ @Test public void selectById() throws IOException { //获得sqlSession // 操作数据库 User o = sqlSession.selectOne("huige.findUserById", 30); //打印结果 System.out.println(o); } @Test public void addUser() throws IOException { User user = new User(); user.setUsername("辉哥"); user.setAddress("863中部软件园"); user.setBirthday(new Date()); user.setSex("男"); sqlSession.insert("huige.addUser",user); } @Test public void updateUser() throws IOException { //先查出来 再修改 User o = sqlSession.selectOne("huige.findUserById", 30); o.setAddress("尚马教育"); o.setSex("女"); sqlSession.update("huige.updateUser",o); } @Test public void deleteUser() throws IOException { sqlSession.delete("huige.deleteUser",10); } @Test public void searchUser() throws IOException { List<User> users = sqlSession.selectList("huige.searchUser", "小"); users.forEach(user -> System.out.println(user)); } @After public void release(){ System.out.println("release方法打印了"); sqlSession.commit(); sqlSession.close(); try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
其实每次操作数据库时 先执行init 操作完数据库之后 又执行release 也就是说 每次都会初始化一个sqlSession 如果全局就一个sqlsession时 这种方式 就不可以了
9. myBatis的dao开发
9.1. 常见dao接口
package com.shangma.cn.dao; import com.shangma.cn.entity.User; public interface UserDao { //根据id查询 User findById(Integer id); //添加用户 void addUser(User user); }
9.2. 创建实现类
package com.shangma.cn.dao.impl; import com.shangma.cn.dao.UserDao; import com.shangma.cn.entity.User; import org.apache.ibatis.session.SqlSession; public class UserDaoImpl implements UserDao { private SqlSession sqlSession; public UserDaoImpl(SqlSession sqlSession) { this.sqlSession = sqlSession; } @Override public User findById(Integer id) { // 操作数据库 User o = sqlSession.selectOne("huige.findUserById", 30); return o; } @Override public void addUser(User user) { sqlSession.insert("huige.addUser",user); } }
9.3. 编写测试类
public class TestDemo3 { SqlSessionFactory sqlSessionFactory; SqlSession sqlSession; UserDao userDao; InputStream inputStream; @Before public void init() throws IOException { System.out.println("init方法打印了"); //配置文件路径 String resource = "mybatis.xml"; //通过路径加载配置文件 inputStream = Resources.getResourceAsStream(resource); //获得sqlsessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); userDao = new UserDaoImpl(sqlSession); } /** * 通过id 查询 */ @Test public void selectById() throws IOException { System.out.println(userDao.findById(30)); } @Test public void addUser() throws IOException { User user = new User(); user.setUsername("凤姐"); user.setAddress("天堂地狱"); user.setBirthday(new Date()); user.setSex("女"); userDao.addUser(user); System.out.println(user.getId()); } @After public void release(){ System.out.println("release方法打印了"); sqlSession.commit(); sqlSession.close(); try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
10.myBatis的Mapper开发(重点)
Mapper代理的方式 主要是解决 不写dao实现类 程序员只需要编写Mapper接口就可以了 但满足规范时 MyBatis 会自动生成Mapper的代理实现类 操作
10.1. Mapper代理书写规范
-
Mapper接口的完整路径 要和Mapper中的namespace一致
-
Mapper接口中的方法 要和映射文件中select update insert delete标签中的 id值一致
-
Mapper接口中方法的参数只能有一个 并且类型要和映射文件中select update insert delete标签中的parameterType的类型一致 、
-
Mapper接口中返回值要和要和映射文件中select update insert delete标签中的resultType或者resultMap的类型一致
10.2. 编写Mapper接口
public interface UserMapper { //查询所有 List<User> selectAll(); //根据id查询 User selectById(Integer id); //添加用户 void saveUser(User user); }
10.3. 编写配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.shangma.cn.mapper.UserMapper"> <!--查询所有 --> <select id="selectAll" resultType="com.shangma.cn.entity.User"> select * from user; </select> <!--根据id查询--> <select id="selectById" parameterType="java.lang.Integer" resultType="com.shangma.cn.entity.User"> select * from user where id = #{id} </select> <!--添加用户--> <insert id="saveUser" parameterType="com.shangma.cn.entity.User"> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select last_insert_id(); </selectKey> insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address}) </insert> </mapper>
10.4. 编写测试类
public class MapperTest { @Test public void testMapper() throws IOException { String path = "mybatis.xml"; InputStream in = Resources.getResourceAsStream(path); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); SqlSession sqlSession = sqlSessionFactory.openSession(true);//设置为true时 自动提交事务 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //查询所有 // List<User> users = mapper.selectAll(); // users.forEach(user -> System.out.println(user)); //根据id查询 //System.out.println(mapper.selectById(30)); // 添加 User user = new User(); user.setUsername("腾格尔"); user.setBirthday(new Date()); user.setSex("男"); mapper.saveUser(user); sqlSession.close(); in.close(); } }
11.全局配置文件讲解
11.1. 名字的规范
全局配置文件的名字 可以随意写 想怎么写 怎么写 但是一般的情况下 会叫如下几个名字
-
sqlMapperConfig.xml
-
mybatis-config.xml
11.2. 数据源问题
11.3. 连接信息抽出
11.3.1. 编写properties文件
11.3.2. 加载配置文件
11.3.3. 读取配置文件
11.4. 别名问题(了解)
我们的 参数类型 和 返回值类型 如果是引用类型 可以起别名
11.4.1. 起别名
-
方式一:
<typeAliases>
<typeAlias type="com.shangma.cn.entity.User" alias="user"/>
</typeAliases>
-
方式二:
<typeAliases>
<!--指定包名时 别名就是包中对应类的类名 不区分大小写-->
<package name="com.shangma.cn.entity"/>
</typeAliases>
11.4.2. 使用别名
11.5. mapper的属性值
11.5.1. resource属性
这个属性的值 是类路径下的资源
<mappers>
<!--mapper的写法 resource 表示从src下(类路径下 开始找 使用文件夹的形式 而不是.)-->
<mapper resource="com/shangma/cn/mapper/user.xml"/>
</mappers>
11.5.2. url属性
这个属性的值 表示完整路径 带盘符 带协议
<mappers>
<mapper url="file:///F:\mybaits01\src\com\shangma\cn\mapper\user.xml"/>
</mappers>
11.5.3. class属性
这个属性值 表示 mapper接口的完整路径
要求:接口名称要和mapper文件名一致 并且在同一个目录下
11.5.4. 开发中的写法
直接写包名 这样的话 如果mapper映射文件比较多的时候 可以统一设置
不需要再一个一个单独设置了
要求:接口名称要和mapper文件名一致 并且在同一个目录下
<mappers>
<package name="com.shangma.cn.mapper"/>
</mappers>
12. 映射文件
-
12.1. parameterType
-
表示参数类型
-
取值
-
基本数据类型
-
map
-
自定义类型
-
包装类
-
12.1.1. 基本数据类型
<!-- 基本数据类型 parameterType="java.lang.Integer" 可以写包装类 类的完整路径 parameterType="int" 可以写别名 --> <select id="selectById" parameterType="int" resultType="user"> select * from user where id = #{id} </select>
12.1.2. 实体类
<!-- 如果是实体类 parameterType="com.shangma.cn.entity.User" 写类的完整路径 如果起了别名 例如 <typeAliases> <package name="com.shangma.cn.entity"/> </typeAliases> 则可以写别名 parameterType="user" 则使用时 #{}是这个实体类中的属性名 --> <insert id="saveUser" parameterType="user"> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select last_insert_id(); </selectKey> insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address}) </insert>
12.1.3. 包装类
-
创建包装类
public class UserExt { private User user; private String like="辉"; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String getLike() { return like; } public void setLike(String like) { this.like = like; } @Override public String toString() { return "UserExt{" + "user=" + user + ", like='" + like + '\'' + '}'; } }
-
在userMapper中添加内容
// 模糊查询 List<User> searchUser(UserExt userExt);
-
编写映射文件
<select id="searchUser" parameterType="com.shangma.cn.entity.UserExt" resultType="com.shangma.cn.entity.User"> select * from user where sex=#{user.sex} and username like '%${like}%' </select>
-
测试
@Test public void testMapper() throws IOException { String path = "mybaits-config.xml"; InputStream in = Resources.getResourceAsStream(path); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); SqlSession sqlSession = sqlSessionFactory.openSession(true);//设置为true时 自动提交事务 //getMapper表示底层使用了动态代理 UserMapper mapper = sqlSession.getMapper(UserMapper.class); UserExt userExt = new UserExt(); User user = new User(); user.setSex("男"); userExt.setUser(user); List<User> users = mapper.searchUser(userExt); users.forEach(user1 -> System.out.println(user1)); sqlSession.close(); in.close(); }
12.2. resultType
返回值类型
注意点:返回单个实体类和实体类集合时 mapper映射文件中的resultType的类型是一样的
问题:这种单独resultType的方式 依赖于 属性名和表中的列名一致 所以数据会封装到实体类中
12.3. resultMap
如果表中的字段和实体类中的属性名不一致时 我们需要使用 resultMap
-
第一步 修改表中字段
-
第二步:使用resultmap 设置属性和别名的对应关系
<!-- id属性 表示resultmap的唯一标识 不能重复 唯一的 随意写 type 表示返回值的类型 或者可以理解为 指定的是哪个类 result 表示 实体类属性和表的别名的对应关系 column:表示表的列明 property: 表示实体类属性名 如果列是id的话 可以使用id标签 --> <resultMap id="huige" type="user"> <id column="id_" property="id"/> <!--<result column="id_" property="id"/>--> <result column="address_" property="address"/> </resultMap>
-
第三步 : 使用resultMap
-
13. sql 代码片
13.1. 问题演示
13.2. if的写法
<select id="searchUser" parameterType="com.shangma.cn.entity.UserExt" resultMap="huige"> select * from user where 1=1 <if test="user!=null"> and sex=#{user.sex} </if> <if test="like!=null and like != '' "> and username like '%${lile}%' </if> </select>
13.3. where的写法
<select id="searchUser" parameterType="com.shangma.cn.entity.UserExt" resultMap="huige"> select * from user <where> <if test="user!=null"> and sex=#{user.sex} </if> <if test="like!=null and like != '' "> and username like '%${lile}%' </if> </where> </select>
13.4. 其他写法
13.5. foreach 标签使用
-
使用场景 : 查询多个id的用户信息
select * from user where id in(x,x,x)
-
mapper接口中添加方法
List<User> selectByIds(UserExt userExt);
-
编写mapper文件
<!-- collection 要遍历的集合 open 表示开始的内容 close 表示结束的内容 separator 表示分割的内容 item 表示每次遍历出来的内容 --> <select id="selectByIds" parameterType="com.shangma.cn.entity.UserExt" resultMap="huige"> select * from user where id_ in <foreach collection="ids" open="(" close=")" separator="," item="id"> #{id} </foreach> </select>
-
测试
@Test public void testMapper() throws IOException { String path = "mybaits-config.xml"; InputStream in = Resources.getResourceAsStream(path); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); SqlSession sqlSession = sqlSessionFactory.openSession(true);//设置为true时 自动提交事务 UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<Integer> list = new ArrayList<>(); list.add(28); list.add(29); list.add(30); list.add(31); UserExt userExt = new UserExt(); userExt.setIds(list); List<User> users = mapper.selectByIds(userExt); users.forEach(user1 -> System.out.println(user1)); sqlSession.close(); in.close(); }
14. mybatis中的多表关系
实际开发中 表和表之间存在一定的关系 这种关系不一定需要数据库中的约束 例如外键 表的关系 有如下几种
-
一对一
-
一对多
-
多对多
14.1. 环境搭建
14.1.1. 建表建库
CREATE TABLE `cart` ( `cartId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `userId` int(11) NULL DEFAULT NULL, `totalnum` int(11) NULL DEFAULT NULL, `totalmoney` double(255, 0) NULL DEFAULT NULL, PRIMARY KEY (`cartId`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; INSERT INTO `cart` VALUES ('4275a23c41694cc0ae54f2a8d97b024b', 5, 1, 129); INSERT INTO `cart` VALUES ('9e96b8b3a71c4700bfc0a4b164a3887e', 4, 3, 9664); CREATE TABLE `cartitem` ( `cartItemId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `cartId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `pid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `pnum` int(11) NULL DEFAULT NULL, `pmoney` double(255, 0) NULL DEFAULT NULL, PRIMARY KEY (`cartItemId`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; INSERT INTO `cartitem` VALUES ('5c8334e949eb471ca32d8d2c2d5db9ed', '9e96b8b3a71c4700bfc0a4b164a3887e', '1d062d5fcaf147468aa325af6715df18', 1, 5666); INSERT INTO `cartitem` VALUES ('b6a42a8be7584c269399d67b3d2b7452', '9e96b8b3a71c4700bfc0a4b164a3887e', '082d077043e74f08b5c8e82c33990d05', 2, 3998); INSERT INTO `cartitem` VALUES ('ff81edf0755d4f5e8e5475745185de2a', '4275a23c41694cc0ae54f2a8d97b024b', '4e6bc5c119a848da8678e6a4d3ec1057', 1, 129); CREATE TABLE `good` ( `pid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `pname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `price` double(10, 2) NULL DEFAULT NULL, `pimg` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `pdesc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`pid`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; INSERT INTO `good` VALUES ('082d077043e74f08b5c8e82c33990d05', '手机', 1999.00, '/images/shouji.jpg', '手机很快'); INSERT INTO `good` VALUES ('1b64510f93104a7886c334351e465b80', '保暖内衣', 56.00, '/images/baonuan.jpg', '很暖和'); INSERT INTO `good` VALUES ('1d062d5fcaf147468aa325af6715df18', '电视', 5666.00, '/images/dianshi.jpg', '1080P'); INSERT INTO `good` VALUES ('224c796995744ae5a22f6d8d72eefc45', '电脑', 8888.00, '/images/diannao.jpg', '128G内存'); INSERT INTO `good` VALUES ('46ea4fabaf8741a3a455e30c83607086', '卫衣', 99.00, '/images/weiyi.jpg', '裹得很严实'); INSERT INTO `good` VALUES ('4e6bc5c119a848da8678e6a4d3ec1057', '吹风机', 129.00, '/images/chuifengji.jpg', '风很大');