Emotion2Vec+ Large前端交互优化:用户上传体验提升技巧分享
2026/1/19 1:04:24
* 在一对多中,当我们有一个用户,它有个100个订单 在查询用户的时候,要不要把关联的订单查出来? 在查询订单的时候,要不要把关联的用户查出来? * 回答 在查询用户时,用户下的订单应该是,什么时候用,什么时候查询。 在查询订单时,订单所属的用户信息应该是随着订单一起查询出来。* 优点: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表 速度要快。 * 缺点: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时 间,所以可能造成用户等待时间变长,造成用户体验下降。 * 在多表中: 一对多,多对多:通常情况下采用延迟加载 一对一(多对一):通常情况下采用立即加载 * 注意: 延迟加载是基于嵌套查询来实现的<!-- 开启一对多 延迟加载 --> <resultMap id="userMap" type="user"> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <result column="birthday" property="birthday"></result> <!-- fetchType="lazy" 懒加载策略 fetchType="eager" 立即加载策略 --> <collection property="orderList" ofType="order" column="id" select="com.lagou.dao.OrderMapper.findByUid" fetchType="lazy"> </collection> </resultMap> <select id="findAll" resultMap="userMap"> SELECT * FROM `user` </select><settings> <!--所有方法都会延迟加载--> <setting name="lazyLoadTriggerMethods" value="toString()"/> </settings><settings> <!--开启全局延迟加载功能--> <setting name="lazyLoadingEnabled" value="true"/> </settings><!-- 关闭一对一 延迟加载 --> <resultMap id="orderMap" type="order"> <id column="id" property="id"></id> <result column="ordertime" property="ordertime"></result> <result column="total" property="total"></result> <!-- fetchType="lazy" 懒加载策略 fetchType="eager" 立即加载策略 --> <association property="user" column="uid" javaType="user" select="com.lagou.dao.UserMapper.findById" fetchType="eager"> </association> </resultMap> <select id="findAll" resultMap="orderMap"> SELECT * from orders </select>@Test public void testOneCache() throws Exception { SqlSession sqlSession = MyBatisUtils.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user1 = userMapper.findById(1); System.out.println("第一次查询的用户:" + user1); User user2 = userMapper.findById(1); System.out.println("第二次查询的用户:" + user2); sqlSession.close(); }1. 第一次发起查询用户id为41的用户信息,先去找缓存中是否有id为41的用户信息,如果没有,从数据库 查询用户信息。 2. 得到用户信息,将用户信息存储到一级缓存中。 3. 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这 样做的目的为了让缓存中存储的是最新的信息,避免脏读。 4. 第二次发起查询用户id为41的用户信息,先去找缓存中是否有id为41的用户信息,缓存中有,直接从缓 存中获取用户信息。@Test public void testClearOneCache() throws Exception { SqlSession sqlSession = MybatisUtils.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user1 = userMapper.findById(41); System.out.println("第一次查询的用户:" + user1); //调用sqlSession清除缓存的方法 sqlSession.clearCache(); User user2 = userMapper.findById(41); System.out.println("第二次查询的用户:" + user2); }<!-- 每次查询时,都会清除缓存 --> < select flushCache="true"></select><settings> <!-- 因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。 为true代表开启二级缓存;为false代表不开启二级缓存。 --> <setting name="cacheEnabled" value="true"/> </settings><mapper namespace="com.lagou.dao.UserMapper"> <!--当前映射文件开启二级缓存--> <cache></cache> <!-- <select>标签中设置useCache=”true”代表当前这个statement要使用二级缓存。 如果不使用二级缓存可以设置为false 注意: 针对每次查询都需要最新的数据sql,要设置成useCache="false",禁用二级缓存。 --> <select id="findById" parameterType="int" resultType="user" useCache="true" > SELECT * FROM `user` where id = #{id} </select> </mapper>public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; private List<Role> roleList; private List<Order> orderList; }@Test public void testTwoCache() throws Exception { SqlSession sqlSession = MyBatisUtils.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findById(41); System.out.println("第一次查询的用户:" + user); sqlSession.close(); SqlSession sqlSession1 = MyBatisUtils.openSession(); UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); User user1 = userMapper1.findById(41); System.out.println("第二次查询的用户:"+user1); sqlSession1.close(); }1. 映射语句文件中的所有select语句将会被缓存。 2. 映射语句文件中的所有insert、update和delete语句会刷新缓存。1. mybatis的缓存,都不需要我们手动存储和获取数据。mybatis自动维护的。 2. mybatis开启了二级缓存后,那么查询顺序:二级缓存--》一级缓存--》数据库 2. 注意:mybatis的二级缓存会存在脏读问题,需要使用第三方的缓存技术解决问题。* @Insert:实现新增,代替了<insert></insert> * @Delete:实现删除,代替了<delete></delete> * @Update:实现更新,代替了<update></update> * @Select:实现查询,代替了<select></select> * @Result:实现结果集封装,代替了<result></result> * @Results:可以与@Result 一起使用,封装多个结果集,代替了<resultMap></resultMap> * @One:实现一对一结果集封装,代替了<association></association> * @Many:实现一对多结果集封装,代替了<collection></collection>public interface UserMapper { @Select("SELECT * FROM `user`") public List<User> findAll(); @Insert("INSERT INTO `user`(username,birthday,sex,address) VALUES(# {username},#{birthday},#{sex},#{address})") public void save(User user); @Update("UPDATE `user` SET username = #{username},birthday = #{birthday},sex = #{sex},address = #{address} WHERE id = #{id}") public void update(User user); @Delete("DELETE FROM `user` where id = #{id}") public void delete(Integer id); }<!--我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可--> <mappers> <!--扫描使用注解的Mapper类--> <mapper class="com.lagou.mapper.UserMapper"></mapper> </mappers><!--或者指定扫描包含映射关系的接口所在的包也可以--> <mappers> <!--扫描使用注解的Mapper类所在的包--> <package name="com.lagou.mapper"></package> </mappers>public class TestUser extends TestBaseMapper { // 查询 @Test public void testFindAll() throws Exception { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> list = userMapper.findAll(); for (User user : list) { System.out.println(user); } } // 添加 @Test public void testSave() throws Exception { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setUsername("于谦"); user.setBirthday(new Date()); user.setSex("男"); user.setAddress("北京德云社"); userMapper.save(user); } // 更新 @Test public void testUpdate() throws Exception { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setId(49); user.setUsername("郭德纲"); user.setBirthday(new Date()); user.setSex("男"); user.setAddress("北京德云社"); userMapper.update(user); } // 删除 @Test public void testDelete() throws Exception { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.delete(49); } }SELECT * FROM orders; SELECT * FROM `user` WHERE id = #{订单的uid};public interface OrderMapper { @Select("SELECT * FROM orders") @Results({ @Result(id = true, column = "id", property = "id"), @Result(column = "ordertime", property = "ordertime"), @Result(column = "money", property = "money"), @Result(property = "user", javaType = User.class, column = "uid", one = @One(select = "com.lagou.mapper.UserMapper.findById", fetchType = FetchType.EAGER)) }) public List<Order> findAllWithUser(); }public interface UserMapper { @Select("SELECT * FROM `user` WHERE id = #{id}") public User findById(Integer id); }@Test public void testOrderWithUser() throws Exception { OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class); List<Order> list = orderMapper.findAllWithUser(); for (Order order : list) { System.out.println(order); } }SELECT * FROM `user`; SELECT * FROM orders where uid = #{用户id};public interface UserMapper { @Select("SELECT * FROM `user`") @Results({ @Result(id = true, column = "id", property = "id"), @Result(column = "brithday", property = "brithday"), @Result(column = "sex", property = "sex"), @Result(column = "address", property = "address"), @Result(property = "orderList", javaType = List.class, column = "id" , many = @Many(select = "com.lagou.mapper.OrderMapper.findByUid")) }) public List<User> findAllWithOrder(); }public interface OrderMapper { @Select("SELECT * FROM orders WHERE uid = #{uid}") public List<Order> findByUid(Integer uid); }@Test public void testUserWithOrder() throws Exception { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> list = userMapper.findAllWithOrder(); for (User user : list) { System.out.println(user); } }SELECT * FROM `user`; SELECT * FROM role r INNER JOIN user_role ur ON r.`id` = ur.`rid` WHERE ur.`uid` = #{用户id};public interface UserMapper { @Select("SELECT * FROM `user`") @Results({ @Result(id = true, column = "id", property = "id"), @Result(column = "brithday", property = "brithday"), @Result(column = "sex", property = "sex"), @Result(column = "address", property = "address"), @Result(property = "roleList", javaType = List.class, column = "id" , many = @Many(select = "com.lagou.mapper.RoleMapper.findByUid")) }) public List<User> findAllWithRole(); }public interface RoleMapper { @Select("SELECT * FROM role r INNER JOIN user_role ur ON r.`id` = ur.`rid` WHERE ur.`uid` = #{uid}") public List<Role> findByUid(Integer uid); }@Test public void testUserWithRole() throws Exception { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> list = userMapper.findAllWithRole(); for (User user : list) { System.out.println(user); } }<settings> <!-- 因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。 为true代表开启二级缓存;为false代表不开启二级缓存。 --> <setting name="cacheEnabled" value="true"/> </settings>@CacheNamespace public interface UserMapper {...}* fetchType = FetchType.LAZY 表示懒加载 * fetchType = FetchType.EAGER 表示立即加载 * fetchType = FetchType.DEFAULT 表示使用全局配置* 注解开发和xml配置优劣分析 1.注解开发和xml配置相比,从开发效率来说,注解编写更简单,效率更高。 2.从可维护性来说,注解如果要修改,必须修改源码,会导致维护成本增加。xml维护性更强。