首页
Bilibili
GitHub
友链
留言
相册
更多
归档
Search
1
MybatisPlus的坑( 自动驼峰命名)
115 阅读
2
欢迎来到ZzRGd的博客
59 阅读
3
初识JAVA及特性
56 阅读
4
解决Idea中注入Mapper警告的6个方法!
54 阅读
5
配置文件YAML基本语法
52 阅读
👋活在当下
🥇学习
WEB前端
CSS
JavaScript
JAVA
登录
/
注册
Search
标签搜索
JAVA
Spring Boot
笔记
学习
锁
JUC
Git
仓库
MySql
Mybatis
Mybatis-Plus
踩雷
高并发
spring cloud
Gateway
分布式
ZzRG
累计撰写
25
篇文章
累计收到
1
条评论
首页
栏目
👋活在当下
🥇学习
WEB前端
CSS
JavaScript
JAVA
页面
Bilibili
GitHub
友链
留言
相册
归档
搜索到
3
篇与
的结果
2022-06-24
解决Idea中注入Mapper警告的6个方法!
使用Mybaits的时候,注入mapper的是一直会有一个红色的警告,虽然不影响代码的运行,但对有强迫症的小伙伴来说,总是有些闹心!接下来告诉大家去掉这些警告的方法。1. 为 @Autowired 注解设置required = false: 使用 @Autowired 注解时,若希望允许null值,可设置required = false。 @Autowired(required = false) private UserMapper userMapper;这样就不会有警告了。原因很好理解:IDEA认为userMapper是个null,给了警告;加上required = false后,使用 @Autowired 注解不再去校验userMapper是否存在了。也就不会有警告了。但是对于一个庞大的既有项目,可能到处都在引用Mapper,总不能到处都补上 required = false 吧。而且对于新手来说,很难一眼看懂加required = false属性只是为了解决IDEA的警告。2. 用 @Resource 替换 @Autowired。 @Resource private UserMapper userMapper;这样也不会再有讨厌的警告。但是如果一个项目已经大量使用@Autowired,然后为了个警告到处改成@Resource,难免会有些麻烦。3. 在Mapper接口上加上@Repository注解。 @Mapper @Repository public interface UserMapper { } @Autowired private UserMapper userMapper;这样也不会有警告,如果你用@Component替换@Repository也是可以的。原理大致:IDEA不是认为 userMapper 是个null,加个@Repository注解骗一下IDEA就好了。4.用Lombok:也可以解决警告的问题,但是如果手写成Lombok生成的代码,Idea依然会报警告。对于不会使用Lombok的小伙伴可参见 Lombok官方文档!5.把IDEA的警告关掉,不推荐这么做。6.安装mybatis plugin插件,但是这个插件时收费的。
2022年06月24日
54 阅读
0 评论
0 点赞
2022-06-21
Mybatis入门
{collapse}{collapse-item label="1、Mybatis入门" open}1.1、创建核心模块编写mybatis的核心配置文件<?xml version="1.0" encoding="UTF-8"?> <!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"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="juzi" /> </dataSource> </environment> </environments> <!-- 引入映射文件--> <mappers> <mapper resource="com/zzrg/dao/UserMapper.xml"/> </mappers> </configuration>编写mybatis工具类/** * @author ZzRG * @version 1.0 */ public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { //使用mybatis获取sqlSessionFactory对象 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //获取sqlSession的实例 //sqlSession 完全包含了面向数据库执行的sql命令所需要的方法 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }1.2、编写代码实体类/** * @author ZzRG * @version 1.0 */ //实体类 public class User { private int id; private String name; private String pwd; public User() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } } Dao接口public interface UserDao { List<User> getUserList(); }接口的实现类 由原来的UserDaoImpl转变成一个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"> <!-- namespace=绑定一个对应的Dao/Mapper接口--> <mapper namespace="com.zzrg.dao.UserDao"> <!-- select语句--> <select id="getUserList" resultType="com.zzrg.pojo.User"> select * from mybatis.user </select> </mapper>1.3、测试/** * @author ZzRG * @version 1.0 */ public class UserDaoTest { @Test public void test(){ // 第一步:获取SqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //执行SQL //方式一 getMapper UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> userList = userDao.getUserList(); for (User user : userList) { System.out.println(user); } //关闭sqlSession sqlSession.close(); } } 注意:测试有可能出现问题初始化异常The error may exist in com/zzrg/dao/UserMapper.xmlUserMapper.xml不存在,也就是说UserMapper.xml这个配置文件没有生效报错原因:maven的配置文件默认放在resources目录下,这里把它放到了java目录下了,导致配置文件导不出来这属于资源过滤问题解决方法: 需要手动配置资源过滤,让它把java目录下的properties和xml等配置文件的过滤开启,使它们能够被导出,在pom.xml中配置开启过滤 <!--在build中配置resources,来防止我们资源导出失败的问题--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>报空指针异常原代码中上面的private static SqlSessionFactory sqlSessionFactory;已经提升了作用域,要把下面的 SqlSessionFactory去掉,SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);不然报空指针异常。即代码重新修改后变private static SqlSessionFactory sqlSessionFactory; static{ try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); }{/collapse-item}{collapse-item label="2、CRUD"}1、namespacenamespace中的包名要和Dao/Mapper接口名字一致2、select选择,查询语句;id:就是对应的namespace中的方法;resultType:Sql语句执行的返回值!parameterType:参数类型!编写接口 //根据ID查询用户 User getUserById(int id);编写对应的Mapper中的sql语句 <select id="getUserById" parameterType="int" resultType="com.zzrg.pojo.User"> select * from mybatis.user where id = #{id} </select>测试 @Test public void getUserById(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); User user = userDao.getUserById(1); System.out.println(user); sqlSession.close(); }3、Insert //insert一个用户 int addUser(User user); <insert id="addUser" parameterType="com.zzrg.pojo.User"> insert into mybatis.user(id,name,pwd) values (#{id},#{name},#{pwd}) </insert> //增删改需要提交事务 @Test public void addUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); int add = userDao.addUser(new User(4, "李松", "123456789")); if (add>0){ System.out.println("插入成功"); } //提交事务 sqlSession.commit(); sqlSession.close(); }4、update //修改用户 int updateUser(User user); <update id="updateUser" parameterType="com.zzrg.pojo.User"> update mybatis.user set name=#{name},pwd=#{pwd} where id =#{id}; </update> @Test public void updateUser() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); int updateUser = userDao.updateUser(new User(4, "王五", "123456789")); //提交事务 if (updateUser>0){ System.out.println("修改成功"); } sqlSession.commit(); sqlSession.close(); } 5、Delete //删除一个用户 int deleteUser(int id); <delete id="deleteUser" parameterType="int"> delete from mybatis.user where id = #{id}; </delete> @Test public void deleteUser() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); int deleteUser = userDao.deleteUser(4); //提交事务 if (deleteUser>0){ System.out.println("删除成功"); } sqlSession.commit(); sqlSession.close(); }注意点://增删改需要提交事务!6、扩展内容假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应该考虑MapMap传递参数,直接在sql中取key即可!【parameterType="map"】对象传递参数,直接sql中取对象的属性即可!【parameterType="Object"】只是一个基本类型参数的情况下,可以直接在sql中取到!多个参数用Map,或者注解! //万能的Map int addUser2(Map<String,Object> map); <!--对象中的属性,可以直接取出来 传递Map的key--> <insert id="addUser" parameterType="map"> insert into mybatis.user(id,e,pwd) values (#{userid},#{username},#{passWord}); </insert> @Test public void addUser2(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("userid",5); map.put("username","hello"); map.put("passWord","222333111"); userDao.addUser2(map); //提交事务 sqlSession.commit(); sqlSession.close(); }7、模糊查询Java代码执行的时候,传递通配符%%List<User> getUserLike(String value);在sql拼接中使用通配符!<select id="getUserLike" resultType="com.zzrg.pojo.User"> select * from mybatis.user where name like "%"#{value}"%"; </select>@Test public void getUserLike() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> userList = userDao.getUserLike("%李%"); for (User user : userList){ System.out.println(user); } sqlSession.close(); }{/collapse-item}{collapse-item label="3、配置解析"}1、配置文件mybatis-config.xmlMybatis的配置文件包含了Mybatis行为的设置和属性信息configuration(配置) properties(属性) settings(设置) typeAliases(类型别名) typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) environments(环境配置) environment(环境变量) transactionManager(事务管理器) dataSource(数据源) databaseIdProvider(数据库厂商标识) mappers(映射器)2、环境变量(environments)Mybatis可以配置成适应多种环境不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。学会使用配置多套环境!Mybatis默认的事务 管理器就是JDBC,连接池:POOLED3、属性(properties)通过properties属性来实现引用配置文件这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设。【db.properties】编写配置文件--db. propertiesdriver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8 username=root password=juzi核心配置文件中映入 <!-- 引入外部配置文件--> <properties resource="db.properties"> <property name="username" value="root"/> <property name="password" value="juzi"/> </properties>可以直接引入外部文件可以在其中增加一些属性配置如果两个文件有同一个字段,优先使用外部配置文件!4、类型别名(typeAliases)类型别名是为Java类型设置一个短的名字。存在的意义仅用来减少类完全限定的冗余。 <!-- 可以给实体类起别名--> <typeAliases> <typeAlias type="com.zzrg.pojo.User" alias="User"/> </typeAliases>也可以指定一个包名,Mybatis会在包名下搜需要的Java Bean,比如:扫描实体类的包,它的默认别名就为了这个类的 类名,首字母小写!<!-- 可以给实体类起别名--> <typeAliases> <package name="com.zzrg.pojo"/> </typeAliases>在实体类比较少的时候,使用第一种方式。如果实体类十分多,建议使用第二种。第一种可以DIY别名,第二种则·不行· ,如果非要改,需要在实体上增加注解。@Alias("hello") public class User {}5、设置这是MyBatis 中极为重要的调整设置,它们会改变MyBatis的运行时行为。6、其他配置typeHandlers(类型处理器)objectFactory(对象工厂)plugins插件mybatis-generator-coremybatis-plus通用mapper7、映射器(mappers)MapperRegistry:注册绑定我们的Mapper文件;方式一:【推荐】<!--每一个Mapper. XML都需要在Mybatis核心配置文件中注册!--> <mappers> <mapper resource="com/zzrg/dao/UserMapper.xml"/> </mappers>方法二:<!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册! --> <mappers> <mapper class="com.zzrg.dao.UserMapper"/> </mappers>注意点:接口和他的Mapper配置文件必须同名!接口和他的Mapper配置文件必须在同一个包下!方法三:使用扫描包进行注入绑定 <mappers> <!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!--> <package name="com.zzrg.dao"/> </mappers>注意点:接口和他的Mapper配置文件必须同名!接口和他的Mapper配置文件必须在同一个包下!8、生命周期和作用域生命周期,和作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题。sqlSessionFactoryBuilder:一旦创建了SqlSessionFactory,就不再需要它宁局部变量sqlSessionFactory:说白了就是可以想象为︰数据库连接池SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。因此SqlSessionFactory的最佳作用域是应用作用域。最简单的就是使用单例模式或者静态单例模式。SqlSession连接到连接池的一个请求sqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。用完之后需要赶紧关闭,否则资源被占用!用完之后需要赶紧关闭,否则资源被占用!这里面的每一个Mapper,就代表一个具体的业务!{/collapse-item}{collapse-item label="4、解决属性名和字段名不一致的问题"}数据库中的字段新建一个项目,拷贝之前的,情况测试实体类字段不一致的//select * from mybatis.user where id = #{id} //类型处理器 //select id,name,pwd from mybatis.user where id = #{id}解决方法:起别名<select id="getuserById" resu1tType="com.zzrg.pojo.User"> select id, name , pwd as password from mybatis.user where id = #{id} </select>1、resultMap结果集映射id name pwd id name password<!--结果集映射--> <resultMap id="UserMap" type="User"> <!-- colum数据库中的字段 property实体类中的属性--> <result column="id" property="id"/> <result column="name" property="name"/> <result column="pwd" property="password"/> </resultMap>resultMap元素是MyBatis中最重要最强大的元素ResultMap的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。ResultMap最优秀的地方在于,虽然你已经对它相当了解了,但是根本就不需要显式地用到他们。如果世界总是这么简单就好了。多对一!{/collapse-item}{collapse-item label="5、日志"}1、日志工厂如果一个数据操作,出现异常,我们需要采取措施排错,日志就是最好的助手!如:sout、debug现在用:日志工厂内置的日志:SLF4JLOG4J(3.5.9 起废弃) 【掌握】LOG4J2JDK_LOGGINGCOMMONS_LOGGINGSTDOUT_LOGGING【掌握】NO_LOGGING在Mybatis中具体使用哪一个日志,在设置中设定!STDOUT_LOGGING标准日志输出 <settings> <!--注意命名规则--> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>2、LOG4J2.1、LOG4J是什么:Log4j是[Apache]的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是[控制台]、文件、[GUI]组件,甚至是套接口服务器、[NT]的事件记录器、UNIX[守护进程]等;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。可以通过一个[配置文件]来灵活地进行配置,而不需要修改应用的代码。2.2、LOG4J的使用入门:#将等级'DEBUG的日志信息输出到console和file这两个目的地,console和lfiLe的定义在下面的代码log4j.rootLogger=DEBUG,console,file #控制台输出的相关设置 log4j.appender.console = org.apache.log4j.ConsoleAppender log4j.appender.console.Target = system.out log4j.appender.console.Threshold=DEBUG log4j.appender.console.1ayout = org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=[%c]-%m%n #文件输出的相关设置 log4j.appender.file = org.apache.log4j.RollingFileAppender log4j.appender.file.File=./log/zzrg.log log4j.appender.file.MaxFilesize=10mb log4j.appender.file.Threshold=DEBUG log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[‰p][%d{yy-MM-dd}][%c]%m%n #目志输出级别 log4j.1ogger.org.mybatis=DEBUG log4j.logger.java.sql=DEBUG 1og4j.1ogger.java.sq1.statement=DEBUG log4j.logger.java.sq1.Resultset=DEBUG log4j.1ogger.java.sq1.PreparedStatement=DEBUG 2.3、配置log4j的实现: <settings> <!--注意命名规则--> <setting name="logImpl" value="LOG4J"/> </settings>2.4、log4j的使用!直接测试!简单使用1.在要使用Log4j的类中,导入包 import org.apache.log4j.Logger;2.日志对象,参数为当前类的classstatic Logger logger = Logger.getLogger(UserDaoTest.class);3.日志级别logger.info("info:进入了testLog4j"); logger.debug("debug:进入了testLog4j"); 1ogger.error("error:进入了testLog4j";{/collapse-item}{collapse-item label="6、分页"}减少数据的处理时间6.1、Limit分页select * from user limit statIndex,pageSize; SELECT * FROM user limit 1,5;使用mybatis实现分页 核心还是SQL接口 //分页 List<User> getUserByLimit(Map<String,Integer>map);Mapper.xml配置<!-- 分页--> <select id="getUserByLimit" parameterType="map" resultType="user"> select * from mybatis.user limit #{statIndex},#{pageSize} </select>测试 @Test public void getUserByLimit(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); HashMap<String, Integer> hashMap = new HashMap<String, Integer>(); hashMap.put("statIndex",0); hashMap.put("pageSize",2); List<User> userByLimit = mapper.getUserByLimit(hashMap); for (User user : userByLimit) { System.out.println(user); } sqlSession.close(); }6.2、RowBounds分页(不推荐)不再是用SQL实现分页接口 //分页二 List<User> getUserByRowBounds();配置文件 <select id="getUserByRowBounds" resultMap="UserMap"> select * from mybatis.user </select>测试 @Test //不在推荐了 public void getUserByRowBounds(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); //通过RowBounds实现 RowBounds rowBounds = new RowBounds(1, 2); //通java代码层实现分页 不推荐了 List<User> list = sqlSession.selectList("com.zzrg.dao.UserMapper.getUserByRowBounds",null,rowBounds); for (User user : list) { System.out.println(user); } sqlSession.close(); }6.3、分页插件了解就行了!{/collapse-item}{collapse-item label="7、使用注解开发"}7.1、面向接口编程-大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程-根本原因︰解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好-在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;-而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。关于接口的理解接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。-接口的本身反映了系统设计人员对系统的抽象理解。-接口应有两类:-第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);-第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface) ;-一个体有可能有多个抽象面。抽象体与抽象面是有区别的。三个面向区别-面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法.-面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现.-接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题.更多的体现就是对系统整体的架构面向接口编码(IOP) 面向接口编程(Interface Oriented Programming:OIP)是一种编程思想,接口作为实体抽象出来的一种表现形式,用于抽离内部实现进行外部沟通,最终实现内部变动而不影响外部与其他实现交互,可以理解成按照这种思想来设计编程的方式就可以称为面向接口编程。 它并不是比面向对象编程更先进的一种独立的编程思想,可以说属于面向对象思想体系的一部分或者说它是面向对象编程体系中的思想精髓之一。上面面向过程和面向对象都举例肚子痛问题解决的例子,结合我们平常生活中经验可以知道,无论男女、都可能出现肚子痛需要上厕所的问题,但是不同的人有不同的方式解决这个问题,不可能每有一个不同处理方式的人就修改一次原来代码,这样不仅不符合面向对象编程中的开闭原则【对拓展开放,对修改关闭】,还可能带来潜在的风险。因此、我们可以将上面面向对象编程中上厕所的五个步骤抽取到【人肚子痛处理接口]和】【马桶接口】,哪个人肚子痛就实现这个【人肚子痛处理接口】,每个马桶类型都实现【马桶接口】(因为不是每个马桶的清理细节都一样,有的是自动,有的是手动)。具体怎么上厕所、冲马桶由你自己定义,你可以站着上、坐着上、倒立上都可以,这样就达到了内部变动而不影响外部交互的目的,我使用这个接口类型接收实现了这个接口的实现者,实现者中的方法逻辑修改了,并不影响我接收它,进行方法调用。7.2、使用注解开发注解在接口上的实现 @Select("select * from user") List<User> getUsers();需要核心配置文件绑定接口<!-- 绑定接口--> <mappers> <mapper class="com.zzrg.dao.UserMapper"/> </mappers>测试 @Test public void Test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> users = mapper.getUsers(); for (User user : users) { System.out.println(user); } sqlSession.close(); }本质:反射机制实现的底层:动态代理!Mybatis纤细的执行流程7.3、CRUD我们可以在工具类创建的时候自动提交事务 //获取sqlSession的实例 //sqlSession 完全包含了面向数据库执行的sql命令所需要的方法 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(true); }编写接口,增加注解 @Select("select * from user") List<User> getUsers(); // 方法存在多个参数,所有参数前面必须加上@Param(id)注解 @Select("select * from user where id = #{id}") User getUserId(@Param("id") int id1); @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{pwd})") int addUser(User user); @Update("update user set name=#{name},pwd=#{pwd} where id =#{id}") int upDateUser(User user); @Delete("delete from user where id = #{uid}") int deleteUser(@Param("uid") int id);测试类的实现 @Test public void Test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); // List<User> users = mapper.getUsers(); // for (User user : users) { // System.out.println(user); // } // User userId = mapper.getUserId(1); // System.out.println(userId); int user = mapper.addUser(new User(5, "李松", "123456")); // int user1 = mapper.upDateUser(new User(5, "李四", "123456")); // mapper.deleteUser(5); System.out.println(user); //已经自动提交事务了,不在需要提交事务 sqlSession.close();注意:配置文件中必须有注册绑定@Param()注解基本类型的参数或者String类型,需要加上引用类型不需要加如果只有一个基本类型的话,可以忽略,但是建议大家都加上!我们在SQL中引用的就是我们这里的@Param()中设定的属性名!7.4、#{}和${}的区别1、#{}是一个占位符,${}只是普通传值2、#{}在使用时,会根据传递进来的值来选择是否加上双引号,因此我们传递参数时一般都是直接传递,不用加双引号;${}则不会,我们需要手动加3、在传递一个参数时,我们在#{}中可以写任意值4、#{}针对SQL注入进行了字符过滤,${}则只是作为普通传值,并没有考虑到这些问题5、#{}的应用场景是为给SQL语句的where字句传递条件;${}的应用场景是为了传递一些需要参与SQL语句语法生成的值{/collapse-item}{collapse-item label="8、LomBok"}官方介绍 Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.Lombok是一个Java库,能自动插入编辑器并构建工具,简化Java开发。通过添加注解的方式,不需要为类编写getter或eques方法,同时可以自动化日志变量。常用注解:@Setter :注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。@Getter :使用方法同上,区别在于生成的是getter方法。@ToString :注解在类,添加toString方法。@EqualsAndHashCode: 注解在类,生成hashCode和equals方法。@NoArgsConstructor: 注解在类,生成无参的构造方法。@RequiredArgsConstructor: 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。@Slf4j: 注解在类,生成log变量,严格意义来说是常量。使用步骤:在IDEA中安装LomBok(小辣椒)插件!在项目中导入LomBok的jar包 <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency>在实体类中加注解Lombok的优缺点优点:能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率让代码变得简洁,不用过多的去关注相应的方法属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等缺点:不支持多种参数构造器的重载虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度{/collapse-item}{collapse-item label="9、多对一处理"}SQL的联表测试环境的搭建导入lombok新建实体类Teacher,Student建立Mapper接口建立Mapper.XML文件在核心配置文件中绑定注册我们的Mapper接口或者文件!测试查询是否能够成功!按照查询嵌套处理<!-- 先查出所有学生的信息--> <!-- 在根据查询出来的学生信息的tid,寻找对应的老师--> <select id="getStudent" resultType="Student"> select * from student </select> <resultMap id="StudentTeacher" type="Student"> <id property="id" column="id"/> <id property="name" column="name"/> <!-- 复杂的属性,我们需要单独处理--> <!-- 对象:association--> <!-- 集合:collection--> <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/> </resultMap> <select id="getTeacher" resultType="Teacher"> select * from teacher where id = #{id} </select>按照结果嵌套处理<!-- 按照结果嵌套处理--> <select id="getStudent2" resultMap="StudentTeacher2"> select s.id sid,s.name sname,t.name tname from student s ,teacher t where s.tid=t.id; </select> <resultMap id="StudentTeacher2" type="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <association property="teacher" javaType="Teacher"> <result property="name" column="tname"/> </association> </resultMap>{/collapse-item}{collapse-item label="10、一对多处理"}环境搭建,和上面一样实体类@Data public class Teacher { private int id; private String name; //一个老师有多个学生 private List<Student> students; }@Data public class Student { private int id; private String name; private int tid; }按照结果嵌套处理<!-- 按结果嵌套查询--> <select id="getTeacher" resultMap="TeacherStudent"> select s.id sid,s.name sname, t.name tname,t.id tid from student s,teacher t where s.tid = t.id and t.id = #{tid} </select> <resultMap id="TeacherStudent" type="Teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> <!-- 复杂的属性,我们需要单独处理--> <!-- 对象:association--> <!-- 集合:collection--> <!-- javaType="":这是一个指定属性类型 集合中的泛型信息,我们使用ofType获取--> <collection property="students" ofType="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap>按照查询嵌套处理 <select id="getTeacher2" resultMap="TeacherStudent2"> select * from mybatis.teacher where id =#{tid} </select> <resultMap id="TeacherStudent2" type="Teacher"> <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/> </resultMap> <select id="getStudentByTeacherId" resultType="Student"> select * from mybatis.student where tid = #{tid} </select>小结关联-association【多对一】集合:collection 【一对多】JavaType & ofTypeJavaType 用来是指定实体类中属性的类型ofType 用来指定映射到List或者集合中的pojo类型 ,泛型中的约束类型!注意点:保证SQL的可读性,通俗易懂注意一对多和多对一,属性名和字段的问题!如果文通不好排查错误,可以使用日志,建议使用Log4j面试高频:MySql引擎 InnoDB底层原理 索引 索引优化{/collapse-item}{collapse-item label="11、动态SQL"}什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句利用动态SQL这一特性可以彻底摆脱这种痛苦。动态 SQL元素和JSTL或基于类似XML的文本处理器相似。在MyBatis之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis采用功能强大的基于0GNL的表达式来淘汰其它大部分元素。 if choose (when, otherwise) trim (where, set) foreach搭建环境CREATE TABLE `blog`( `id` VARCHAR(50) NOT NULL COMMENT '博客id', `title` VARCHAR(100) NOT NULL COMMENT '博客标题', `author` VARCHAR(30) NOT NULL COMMENT '博客作者', `create_time` DATETIME NOT NULL COMMENT '创建时间', `views` INT(30) NOT NULL COMMENT '浏览量' )ENGINE=INNODB DEFAULT CHARSET=utf8创建基础工程文件创建包编写配置文件编写实体类@Data public class Blog { private int id; private String title; private String author; private Date createTime; private int views; }编写实体类对应Mapper接口和Mapper.xml配置文件mybatis settings标签 *mapUnderscoreToCamelCase*属性当查询结果集的列名和pojo的属性名不一样时,且他们有遵从驼峰命名法时,我们可以使用settings标签的 mapUnderscoreToCamelCase属性来解决这个映射问题。怎么算是遵守驼峰命名法如: 列名为: u_id,u_name,u_pwdpojo对应属性名为:uId,uName,uPwd---------------------------------------------------------------------------------列名为: u_a_id,u_a_name,u_a_pwdpojo对应属性名为:uAId,uAName,uAPwd如此,pojo的属性名是驼峰命名法if <select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog where 1=1 <if test="title !=null"> and title = #{title} </if> <if test="author !=null"> and author = #{author} </if> </select>choose、when、otherwise <select id="queryBlogChoose" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <choose> <when test="title !=null"> title = #{title} </when> <when test="author !=null"> and author =#{title} </when> <otherwise> and views = #{views} </otherwise> </choose> </where> </select>trim(where、set) <select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <if test="title !=null"> title = #{title} </if> <if test="author !=null"> and author = #{author} </if> </where> </select> <update id="updateBlog" parameterType="map"> update mybatis.blog <set> <if test="title !=null"> title = #{title}, </if> <if test="author !=null"> author =#{title} </if> </set> where id = #{id} </update>Foreachselect * from user where 1=1 and <foreach item= "id" collection="ids" open="(" separator="or" closs=")"> #{id} </foreach> (id=1 or id=2 or id=3) <select id="queryBlogForeach" parameterType="blog"> select * from mybat1s.Blog <where> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id=#{id} </foreach> </where> </select>SQL片段有的时候,我们可能会将一些功能的部分抽取出来,方便复用!使用SQL标签抽取公共的部分 <sql id="if-title-author"> <if test="title !=null"> title = #{title} </if> <if test="author !=null"> and author = #{author} </if> </sql>在需要使用的地方使用Include标签引用即可 <select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <include refid="if-title-author"></include> </where> </select>注意事项:最好基于单表来定义SQL片段!不要存在where标签{/collapse-item}{collapse-item label="12、缓存"}简介查询:连接数据库,耗资源! 一次查询的结果,给他暂存在一个可以直接取到的地方! -->内存:缓存 我们再次查询相同数据的时候,直接走缓存,就不用走数据库了 什么是缓存[ Cache ]?存在内存中的临时数据。将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。为什么使用缓存?减少和数据库的交互次数,减少系统开销,提高系统效率。什么样的数据能使用缓存?经常查询并且不经常改变的数据。Mybatis缓存MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)。二级缓存需要手动开启和配置,他是基于namespace级别的缓存。为了提 高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存一级缓存一级缓存也叫本地缓存:与数据库同一次会话期间查询到的数据会放在本地缓存中。以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;缓存失效的情况:查询不同的东西增删改操作,可能会改变原来的数据,所以必定会刷新缓存!查询不同的Mapper.xml手动清理缓存!小结:一级缓存默认是开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个区间段 —级缓存相当于一个Map。二级缓存二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存基于namespace级别的缓存,一个名称空间,对应一个二级缓存;工作机制一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;新的会话查询信息,就可以从二级缓存中获取内容;不同的mapper查出的数据会放在自己对应的缓存(map)中;步骤开启全局缓存: <settings> <setting name="cacheEnabled" value="true"/> </settings>在要使用二级缓存的Mapper中开启<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>测试问题:我们需要将实体类序列化!否则就会报错!caused by: java.io.NotserializableException : com.zzrg.pojo.user @Test public void test2(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); SqlSession sqlSession2 = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUserId(1); System.out.println(user); sqlSession.close(); System.out.println("=========================="); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user2= mapper2.queryUserId(1); System.out.println(user2); sqlSession.close(); }小结:只要开启了二级缓存,在同一个Mapper下就有效所有的数据都会先放在一级缓存中;只有当会话提交,或者关闭的时候,才会提交到二级缓冲中!缓存的原理自定义缓存-ehcacheEhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider要在程序中使用ehcache,先要导包<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache --> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.1.0</version> </dependency>导入配置文件 ehcache.xml<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <!-- diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下: user.home – 用户主目录 user.dir – 用户当前工作目录 java.io.tmpdir – 默认临时文件路径 --> <diskStore path="java.io.tmpdir/Tmp_EhCache"/> <!-- defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。 --> <!-- name:缓存名称。 maxElementsInMemory:缓存最大数目 maxElementsOnDisk:硬盘最大缓存个数。 eternal:对象是否永久有效,一但设置了,timeout将不起作用。 overflowToDisk:是否保存到磁盘,当系统当机时 timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 clearOnFlush:内存数量最大时是否清除。 memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。 FIFO,first in first out,这个是大家最熟的,先进先出。 LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。 --> <defaultCache eternal="false" maxElementsInMemory="10000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="259200" memoryStoreEvictionPolicy="LRU"/> <cache name="cloud_user" eternal="false" maxElementsInMemory="5000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" memoryStoreEvictionPolicy="LRU"/> </ehcache>{/collapse-item}{/collapse}结束!!!
2022年06月21日
18 阅读
0 评论
0 点赞
2022-06-12
MySql的学习笔记!
1.创建数据库CHARACTER SET: 指定数据库采用的字符集,如果不指定字符集,默认utf8COLLATE: 指定数据库字符集的校对规则(常用的utf8 bin,utf8 general ci注意默认是utf8 general ci)实例:使用指令创建数据库 CREATE DATABASE 名字;删除数据库指令 DROP DATABASE 名字;创建一个使用utf8字符集的hsp db02数据库REATE DATABASE hsp db02 CHARACTER SET utf8创建一个使用utf8字符集,并带校对规则的hsp db03数据库REATE DATABASE hsp db03 CHARACTER SET utf8 COLLATE utf8 bin校对规则utf8 bin区分大小默认ut_general_ci不区分天小写下面是一条查询的sql , select查询*表示所有字段FROM从哪个表WHERE从哪个字段NAME= 'tom'查询名字是tomSELECT * FROM t1 WHERE NAME=' tom'查看、删除、备份、恢复数据库显示数据库语句: SHOW DATABASES显示数据库创建语句: SHOW CREATE DATABASE db_ name数据库删除语句【一定慎用!】: DROP DATABASE [IF EXISTS] db_ name备份数据库(注意:在DOS执行)命令行 mysqldump-u用户名-p-B数据库1数据库2数据库n>文件名.sql恢复数据库(注意:进入SQLyog再执行) Source文件名.sql备份库的表 mysqldump-u 用户名-p密码数据库表1表2表n >d:\文件名.sql创建表CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype )character set字符集collate校对规则engine引擎 field:指定列名datatype:指定列类型(字段类型) character set :如不指定则为所在数据库字符集 collate:如不指定则为所在数据库校对规则 engine:引擎(这个涉及内容较多,后面单独讲解) 注意:创建表时,要根据需保存的数据创建相应的列,并根据数据的类型定义相应的列类型。例:user表 id 整形name 字符串password 字符串birthday 日期数值型(bit)的使用1.基本使用 mysql> create table t02(num bit(8));mysql> insert into t02 (1,3);mysql> insert into t02 values(2, 65);2.细节说明 . bit字段显示时,按照位的方式显示..查询的时候仍然可以用使用添加的数值·如果一个值只有0,1可以考虑使用bit(1),可以节约空间.位类型。M指定位数,默认值1,范围1-64.使用不多.数值型(小数)的基本使用1.FLOAT/DOUBLE [UNSIGNED]Float单精度精度,Double双精度·2.DECIMAL[M,D] [UNSIGNED]·可以支持更加精确的小数位。M是小数位数(精度)的总数,D是小数点(标度)后面的位数。·如果D是0,则值没有小数点或分数部分。M最大65。D最大是30。如果D被省略,默认是0。如果M被省略,默认是10。·建议:如果希望小数的精度高,推荐使用decimal字符串的基本使用 CHAR(size)固定长度字符串最大255字符VARCHAR(size)可变长度字符串最大65532字节【utf8编码最大21844字符1-3个字节用于记录大小】 字符串使用细节细节 char(4)//这个4表示字符数(最大255),不是字节数,不管是中文还是字母都是放四个,按字符计算. varchar(4)//这个4表示字符数,不管是字母还是中文都以定义好的表的编码来存放数据。 不管是中文还是英文字母,都是最多存放4个,是按照字符来存放的.细节2 char(4)是定长(固定的大小),就是说,即使你插入'aa', 也会占用分配的4个字符的空间. varchar(4)是变长,就是说,如果你插入了'aa',实际占用空间大小并不是4个字符,而是按照实际占用空间来分配 (说明:varchar本身还需要占用1-3个字节来记录存放内容长度) L(实际数据大小) + (1-3)字节细节3 什么时候使用char,什么时候使用varchar 1.如果数据是定长,推荐使用char,比如md5的密码,邮编,手机号,身份证号码等. char(32) 2.如果一个字段的长度是不确定,我们使用varchar,比如:留言,文章查询速度:( char> varchar )细节4 在存放文本时,也可以使用Text数据类型.可以将TEXT列视为VARCHAR列,注意Text不能有默认值.大小0-2^16字节如果希望存放更多字符,可以选择MEDIUMTEXT O-2^24 或者LONGTEXT 0~2^32日期类型的基本使用CREATE TABLE birthday6 (t1 DATE, t2 DATETIME, t3 TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ; timestamp时间戳 mysql> INSERT INTO birthday (t1,t2) VALUES('2022-11-11','2022-11-11 10:10:10');日期类型的细节说明 TimeStamp在Insert和update时,自动更新演示时间相关类型#创建一张表,data , datetime , timestamp CREATE TABLE t14 ( birthday DATE, -- 生日 job_time DATETIME, -- 记录年月日 时分秒 login_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 登陆时间 如果希望login_time自动更新 需配置 ); SELECT * FROM t14; INSERT INTO t14 (birthday, job_time) VALUES ( '2022-11-11', '2022-11-11 10:10:10' ); -- 如果我们更新 t14表的某条记录,login_time 列会自动更新当前的时间修改表-基本介绍使用ALTER TABLE 语句追加,修改,或删除列的语法. 1.添加列ALTER TABLE tablename ADD (column datatype [DEFAULTexpr]fdc[ , column datatype] . . . ) ;2.修改列ALTER TABLE tablename MODIFY (column datatype [DEFAULTexpr][ , column datatype] . . . ) ;3.删除列ALTER TABLE tablename DROP (column) ;4.查看表的结构:desc表名;--可以查看表的列5.修改表名:Rename table表名to新表名6.修改表字符集:alter table表名character set字符集;数据库CRUD语句Insert语句 (添加数据)Update语句 (更新数据)Delete语句 (删除数据)Select语句 (查找数据)说明insert语句的细节 1.插入的数据应与字段的数据类型相同。比如:把'abc'添加到int类型会错误 '33'会进行转型INSERT INTO `goods` (id, goods_name, price) VALUES('33', '我的手机', 3000);2.数据的长度应在列的规定范围内,例如:不能将一个长度为8O的字符串加入到长度为40的列中INSERT INTO `goods` (id, goods_name, price) VALUES(40, '我的手机我的手机我的手机', 3000);3.在values中列出的数据位置必须与被加入的列的排列位置相对应。INSERT INTO `goods` (id, goods_name, price) VALUES('我的手机',40,3000);4.字符和日期型数据应包含在单引号中。INSERT INTO `goods` (id, goods_name, price) VALUES(40,我的手机,3000);5.列可以插入空值[前提是该字段允许为空],insert into table value(null)INSERT INTO `goods` (id, goods_name, price) VALUES(40,'我的手机',NULL);6.insert into tab name (列名..) values (),(),()形式添加多条记录INSERT INTO `goods` (id, goods_name, price) VALUES(40,'我的手机',2300),(44,'海尔手机',2200);7.如果是给表中的所有字段添加数据,可以不写前面的字段名称INSERT INTO `goods` VALUES(41,'我的手机',5000);8.默认值的使用,当不给某个字段值时,如果有默认值就会添加,否则报错如果某个列 没有指定not null 那么当添加数据时,没有给定值,则会默认nullINSERT INTO `goods` (id, goods_name) VALUES(50,'格力手机');update语句使用细节:UPDATE语法可以用新值更新原有表行中的各列。SET子句指示要修改哪些列和要给予哪些值。WHERE子句指定应更新哪些行。如没有WHERE子句,则更新所有的行。如果需要修改多个字段,可以通过set字段1=值1,字段2=值2…….delete语句使用细节如果不使用where子句,将删除表中所有数据。Delete语句不能删除某一列的值(可使用update 设为null或者'')使用delete语句仅删除记录,不删除表本身。如要删除表,使用drop table语句。 drop table 表名;select语句Select语句的注意事项(创建测试表学生表)Select 指定查询哪些列的数据。column指定列名。*号代表查询所有列。From指定查询哪张表。DISTINCT可选,指显示结果时,是否去掉重复数据select语句在where子句中经常使用的运算符 案例:--查询英语分数在80—90之间的同学。 SELECT *FROM student WHEREenglish >=80AND english <=90; SELECT *FROM student WHEREenglish BETWEEN 80 AND 90; -- between .. and ..是闭区间 --查询数学分数为89,9o,91的同学。 SELECT *FROM student WHEREmath = 89 OR math = 90 OR math = 91; SELECT *FROM student wHEREmath IN(89, 90, 91); --查询所有姓李的学生成绩。 SELECT *FROM student WHEREmathIN(89. 90. 91);使用order by子句排序查询结果。SELECT column1 , column2 . column3. . FROM table; order by column ascl desc,...Order by指定排序的列,排序的列既可以是表中的列名,也可以是select语句后指定的列名。Asc升序[默认]、Desc降序ORDER BY子句应位于SELECT语句的结尾。合计/统计函数- count Count返回行的总数select count (*) | count(列名) from tablename [WHERE where_definition]合计函数- sum Sum函数返回满足where条件的行的和-一般使用在数值列select sum(列名) { ,sum(列名)..} from tablename [WHERE where_definition]合计函数- avg AVG函数返回满足where条件的一列的平均值select avg(列名) {,avg(列名)...] from tablename [WHERE where_definition]合计函数- Max/min Max/min函数返回满足where条件的一列的最大/最小值select max(列名) from tablename [WHERE where_definition]使用group by子句对列进行分组[先创建测试表]SELECT column1, column2 . column3. . FROM table group by column使用having子句对分组后的结果进行过滤SELECT column1, column2. column3. . FROM table group by column having ...字符串相关函数数学相关函数rand0)返回一个随机浮点值v,范围在0到1之间(即,其范围为0svS1.0)。若已指定一个整数参数N,则它被用作种子值,用来产生重复序列。时间日期相关函数加密和系统函数流程控制函数查询加强-- 使用where子句 -- ?如何查找1992.1.1后入职的员工 -- 老师说明:在mysql中,日期类型可以直接比较 SELECT * FROM emp WHERE hiredate <='1992-01-01' -- 如何使用1ike操作符(模糊) -- %:表示0到多个人任意字符 _:表示单个字符 SELECT ename, sal FROM emp WHERE ename LIKE 's%' -- ?如何显示首字符为s的员工姓名和工资 SELECT ename, sal FROM emp WHERE ename LIKE 's%' -- ?如何显示第三个字符为大写o的所有员工的姓名和工资 SELECT ename, sal FROM emp WHERE ename LIKE '__O%' -- 如何显示没有上级的雇员的情况 SELECT *FROM enp WHERE mgr IS NULL -- 查询表结构selectinc.sql DESC emp -- 使用order by子句 -- ?如何按照工资的从低到高的顺序,显示雇员的信息 SELECT *FROM emp ORDER BY sal -- ?按照部门号升序而雇员的工资降序排列,显示雇员信息 SELECT *FROM emp ORDER BY deptno ASC,sal DESC;分页查询1.按雇员的id号升序取出,每页显示3条记录,请分别显示第一页,第二页,第三页 -- 第一页 SELECT * FROM emp ORDER BY empno LIMIT 0, 3 -- 第二页 SELECT * FROM emp ORDER BY empno LIMIT 3, 3 -- 第三页 SELECT * FROM emp ORDER BY empno LIMIT 6, 3 -- 公式 -- 第二页 SELECT * FROM emp ORDER BY empno LIMIT 每页显示记录数 * (第几页-1),每页的记录数2.基本语法:select ... limit start, rows 表示从start+1行开始取,取出rows行, start从0开始计算在默认情况下:当两个表查询时,规则 1.从第一张表中,取出一行和第二张表的每一行进行组合,返回结果[含有两张表的所有列].2.一共返回的记录数第一张表行数*第二张表的行数3.这样多表查询默认处理返回的结果,称为笛卡尔集4.解决这个多表的关键就是要写出正确的过滤条件where,需要程序员进行分析mysql约束基本介绍 约束用于确保数据库的数据满足特定的商业规则。在mysql中,约束包括: not null、unique,primary key,foreign key,和check五种. primary key(主键)-基本使用 字段名字段类型primary key用于唯一的标示表行的数据,当定义主键约束后,该列不能重复primary key(主键)-细节说明primary key不能重复而且不能为null。 1.一张表最多只能有一个主键,但可以是复合主键主键的指定方式有两种直接在字段名后指定:字段名primakry key在表定义最后写primary key(列名); 2.使用desc表名,可以看到primary key的情况not nulI(非空) 如果在列上定义了not null,那么当插入数据时,必须为列提供数据。字段名字段类型not nul unique(唯一) 当定义了唯一约束后,该列值是不能重复的。字段名字段类型uniqueunique细节(注意): 如果没有指定not null,则unique字段可以有多个null张表可以有多个unique字段foreign key(外键) 用于定义主表和从表之间的关系:外键约束要定义在从表上,主表则必须具有主键约束或是unique约束.,当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为null(学生/班级图示)FOREIGN KEY(本表字段名) REFERENCES 韦名(丰健名uniaue段包)foreign key(外键)—细节说明外键指向的表的字段,要求是primary key或者是 unique表的类型是innodb,这样的表才支持外键外键字段的类型要和主键字段的类型一致(长度可以不同)外键字段的值,必须在主键字段中出现过,或者为null [前提是外键字段允许为null]一旦建立主外键的关系,数据不能随意删除了.check 用于强制行数据必须满足的条件,假定在sal列上定义了check约束,并要求sal列值在1000~2000之间如果不再1000~2000之间就会提示出错。oracle和sql server均支持check ,但是mysql5.7目前还不支持check ,只做语法校验,但不会生效。基本语法:列名类型check (check条件) user表 id, name, sex(man,woman), sal(大于100小于900)自增长基本介绍字段名 整型 primary key auto_increment添加自增长的字段方式insert into xxx(字段1,字段2….….) values(null,'值'...); insert into xxx(字段2..….) values('值1','值2'..…); insert into xxx values(null,'"值1',...….)自增长使用细节峰一般来说自增长是和primary key配合使用的自增长也可以单独使用[但是需要配合一个unique]自增长修饰的字段为整数型的(虽然小数也可以但是非常非常少这样使用)自增长默认从1开始,你也可以通过如下命令修改altertable表名auto increment = xXX;如果你添加数据时,给自增长字段(列)指定的有值,则以指定的值为准索引索引的类型主健索引,主键自动的为主索引(类型Primary)唯一索引(UNIQUE)普通索引 (INDEX)全文索引(FULLTEXT)[适用于MylSAM]一般开发,不使用mysql自带的全文索引,而是使用:全文搜索Solr和 ElasticSearch (ES)索引使用 1.添加索引(建小表测试id , name )create [UNIQUE] index index_name on tbl_name (col_name [(lengthJ[ASC | DESC] ,……); alter table table_name ADD INDEX [index name][index col_name,... )2.添加主键(索引)ALTER TABLE表名 ADD PRIMARY KEY(列名…);4.删除索引DROP INDEX index name ON tbl_ name, alter table table name drop index index_name;4.删除主键索引比较特别:alter table t_b drop primary key;小结:哪些列上适合使用索引 1.较频繁的作为查询条件字段应该创建索引select * from emp where empno = 12.唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件select * from emp where sex =‘男‘3.更新非常频繁的字段不适合创建索引select * from emp where logincount =14.不会出现在WHERE子句中字段不该创建索引什么是事务事务用于保证数据的一致性它油一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败。如:转账就要用事务来处理,用以保证数据的一致性。事务和锁 当执行事务操作时(dml语句),mysql会在表上加锁,防止其它用户改表的数据.这对用户来讲是非常重要的mysql 数据库控制台事务的几个重要操作start transaction --开始一个事务savepoint保存点名--设置保存点rollback to保存点名--回退事务rollback --回退全部事务commit --提交事务,所有的操作生效,不能回退细节:没有设置保存点多个保存点存储引擎开始事务方式回退事务 在介绍回退事务前,先介绍一下保存点(savepoint).保存点是事务中的点.用于取消部分事务,当结束事务时(commit),会自动的删除该事务所定义的所有保存点.当执行回退事务时,通过指定保存点可以回退到指定的点提交事务 使用commit语句可以提交事务.当执行了commit语句子后,会确认事务的变化、结束事务、删除保存点、释放锁,数据生效。当使用commit语句结束事务子后,其它会话将可以查着到事务变化后的新数据事务细节如果不开始事务,默认情况下,dml操作是自动提交的,不能回滚如果开始一个事务,你没有创建保存点你可以执行 rollback,默认就是回退到你事务开始的状态.你也可以在这个事务中(还没有提交时),创建多个保存点.比如: savepointaaa;执行dml , savepoint bbb;你可以在事务没有提交前,选择回退到哪个保存点.mysql的事务机制需要innodb的存储引擎才可以使用,myisam不好使.开始一个事务start transaction,set autocommit=off;mysql事务隔离级别事务隔离级别介绍 1.多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个连接在获取数据时的准确性。(通俗解释)2.如果不考虑隔离性,可能会引发如下问题:脏读不可重复读幻读●查看事务隔离级别查看当前会话隔离级别select @@tx_isolation;脏读(dirty read): 当一个事务读取另一个事务尚未提交的修改时,产生脏读不可重复读(nonrepeatable read): 同一查询在同一事务中多次进行,由于其·他提交事务所做的修改或删除,每次返回不同的结果集,此时发生不可重复读。幻读(phantom read): 同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻读。事务隔离级别概念:Mysql隔离级别定义了事务与事务之间的隔离程度。1.查看当前会话隔离级别 select @@tx_isolation;2.查看系统当前隔离级别select @@global.tx_isolation;3.设置当前会话隔离级别set session transaction isolation level repeatable read;4.设置系统当前隔离级别set global transaction isolation level repeatable read;5.mysql默认的事务隔离级别是repeatable read,一般情况下,没有特殊要求,没有必要修改(因为该级别可以满足绝大部分项目需求)全局修改,修改my.ini配置文件,在最后加上 可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ.SERIALIZABLE.[mysqld]transactien-isolation = REPEATABLE-READ事务的acid特性 1.原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。2.一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态3.隔离性(lsolation)事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。4.持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响存储引擎基本介绍1.MySQL的表类型由存储引擎(Storage Engines)决定,主要包括MylSAM、innoDB、Memory等。2.MySQL数据表主要支持六种类型,分别是:CSV、Memory、ARCHIVE、MRG MYISAM、MYISAM、InnoBDB。3.这六种又分为两类,一类是”事务安全型”(transaction-safe)比如:InnoDB;其余都属于第二类,称为”非事务安全型”(non-transaction-safe)[mysiam和memory]。。●细节说明 我这里重点给大家介绍三种:MylSAM、InnoDB、MEMORYMylSAM不支持事务、也不支持外键,但其访问速度快,对事务完整性没有要求InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起MylSAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。MEMORY存储引擎使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。但是一旦服务关闭,表中的数据就会丢失掉,表的结构还在。如何选择表的存储引擎如果你的应用不需要事务,处理的只是基本的CRUD操作,那么MylSAM是不二选择,速度快如果需要支持事务,选择lnnoDB。Memory存储引擎就是将数据存储在内存中,由于没有磁盘I./O的等待,速度极快。但由于是内存存储引擎,所做的任何修改在服务器重启后都将消失。(经典用法用户的在线状态().视图的基本使用create view视图名as select语句alter view视图名as select语句--更新成新的ShoW CREATE VIEW视图名drop view视图名1,视图名2视图细节讨论 1.创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式:视图名.frm)2.视图的数据变化会影响到基表,基表的数据变化也会影响到视图[insert update delete ] ----针对前面的雇员管理系统-----mysql> create view myview as select empno ,ename , job, comm from emp;mysql> select * from myview;mysql> update myview set comm=200 where empno=7369;//修改视图,对基表都有变化mysql> update emp set comm=100 where empno=7369;//修改基表,对视频也有变化3.视图中可以再使用视图视图最佳实践 1.安全。一些数据表有着重要的信息。有些字段是保密的,不能让用户直接看到。这时就可以创建一个视图,在这张视图中只保留一部分字段。这样,用户就可以查询自己需要的字段,不能查看保密的字段。2.性能。关系数据库的数据常常会分表存储,使用外键建立这些表的之间关系。这时,数据库查询通常会用到连接(JOIN)。这样做不但麻烦,效率相对也比较低。如果建立一个视图,将相关的表和字段组合在一起,就可以避免使用JOIN查询数据。3.灵活。如果系统中有一张旧的表,这张表由于设计的问题,即将被废弃。然而,很多应用都是基于这张表,不易修改。这时就可以建立一张视图,视图中的数据直接映射到新建的表。这样,就可以少做很多改动,也达到了升级数据表的目的。Mysql用户mysql中的用户,都存储在系统数据库mysql中user表中其中user表的重要字段说明:1.host:允许登录的“位置”,localhost表示该用户只允许本机登录,也可以指定ip地址,比如:192.168.1.1002.user:用户名;3.authentication_string:密码,是通过mysql的password()函数加密之后的密码。创建用户 create user '用户名' @ '允许登录位置' identified by'密码'说明:创建用户,同时指定密码删除用户 drop user '用户名' @ '允许登录位置';用户修改密码 修改自己的密码;set password = password(密码');修改他人的密码(需要有修改用户密码权限):set password for '用户名'@"登录位置"= password('密码);给用户授权基本语法:grant all on *.* to '用户名' @ '登录位置'【identified by '密码'】说明: 1.权限列表,多个权限用逗号分开grant select on ...... grant select,delete, create on ...... grant all 【privileges】 on .....//表示赋予该用户在该对象上的所有权限2.特别说明**∶代表本系统中的所有数据库的所有对象(表,视图,存储过程)库.*:表示某个数据库中的所有数据对象(表,视图,存储过程等)3, identified by可以省略,也可以写出.(1)如果用户存在,就是修改该用户的密码。(2)如果该用户不存在,就是创建该用户!回收用户授权基本语法:revoke 权限列表 on 库.对象名 from '用户名'@'登录位置';权限生效指令如果权限没有生效,可以执行下面命令.基本语法:FLUSH PRIVILEGES;细节说明 1.在创建用户的时候,如果不指定Host则为%,%表示表示所有IP都有连接权限create user xXX;2.你也可以这样指定create user 'xxx'@'192.168.1.%' 表示xoxx用户在192.168.1.*的ip可以登录mysql3.在删除用户的时候,如果host 不是 % 需要明确指定 '用户'@'host值'
2022年06月12日
24 阅读
0 评论
0 点赞