1.mybatis是一个Java持久层框架,mybatis是对jdbc的封装。dao是持久层接口
2.jdbc编程中的问题:企业开发中,根据项目大小,特点进行技术选型,jdbc也是技术选型的参考。
jdbc操作数据库效率比框架要高。
3.PreparedStatement是预编译的statement,通过statement发起数据库的操作。Preparedstatement,
可以防止sql注入,执行数据库效率高。通过PreparedStatement发送到数据库的sql语句,数据库会对
这些语句进行缓存。二次发送时,可以省略编译的步骤。
4.jdbc问题总结:
①数据库连接频繁的创建与关闭,极大浪费数据库资源。
*解决该问题可以用数据库连接池(c3p0)
②sql语句是硬性编码,硬性编码不利于系统维护。如果需求变更,需要修改sql,就需要修改Java代码
*将sql语句统一配置在文件中,修改sql不需要修改Java代码
③向PreparedStatement占位符设置参数存在硬编码(参数位置)问题
*将sql中的占位符配置在配置文件中
④遍历结果集存在硬编码问题
*自动进行sql查询结果向Java对象映射
5.mybatis架构:
①它有一个最基础的配置文件,SqlMapperConfig.xml.(全剧配置文件)。它的作用是加载mybatis的运行环境
它的作用是加载mybatis的运行环经所需要的东西,如数据源,事务
②mapper.xml(配置sql语句)
*mybatis的重点不是环境,而是sql语句,会写sql语句
6.SqlSessionFactory(会话工厂)的作用是创建SqlSession,sqlSession的作用是操作数据库
SqlSession是面向用户的接口,它里面的方法就是CRUD方法
7.内部并不是SqlSession干活,而是Executor,数据库操作的执行器。
Excutor也是一个接口,它有默认执行器和缓存执行器
8.MappedStatement(mybatis的封装对象),封装sql语句
9.mapped,mapping,映射。
10.log4j.properties 作用:① Log4j是Apache的一个开放源代码项目,通过使用Log4j,
我们可以控制日志信息输送的目的地是控制台、文件、GUI组件②通过定义每一条日志信息的级别,
我们能够更加细致地控制日志的生成过程
11.POJO:简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。
12.映射:在JavaBean类与数据库字段里,如果有想匹配的名称。数据库就会把字段的值赋给JavaBean类的属性
13.mapper.xml,命名方式:表明+mapper.xml
14.selectOne(String statement,Object obj),用于查找单条记录。否则会报这样的错误
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned
by selectOne(), but found: 2
selectList(String statement,Object obj).
15.占位符:①#{},表示一个占位符,向该占位符传参数时,mybatis会自动拼接。比如传入字符串,mybatis最终拼接好
的sql就是参数两边加单引号。
②${},表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中,缺点:因为是拼接串,不能防止sql注入
16.mybatis的配置:
①编写SqlMapConfig.xml:
--------------------------------------------------------------------------------------------------------------------
<!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"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/newstart"/>
<property name="username" value="root"/>
<property name="password" value="fusong"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="config\account.xml"/>
</mappers>
</configuration>
①当mybatis与spring结合使用时,<environments这个标签就废掉了。
②<mappers>标签是mybatis提供的,要加到<configuration>里,进行sql语句的管理。
--------------------------------------------------------------------------------------------------------------------
②编写account.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 namespace="account">
<select id="selectByMoney" parameterType="double" resultType="com.fusong.POJO.Account">
select * from account WHERE money=#{id}
</select>
<select id="selectName" parameterType="string" resultType="com.fusong.POJO.Account">
select * from account WHERE name LIKE #{id}
</select>
<select id="selectName2" parameterType="string" resultType="com.fusong.POJO.Account">
select * from account WHERE name LIKE "%${value}%"
</select>
</mapper>
①id="selectByMoney",这里的id看作具有一个唯一标识的statement。在后面程序里我们要找它。
②#{},表示一个占位符,当这里面传入简单类型的参数时,这里面的名称随意
③parameterType:输入参数的类型,通过#{}接收程序里输入的参数
④resultType:输出结果的类型,不管输出单条还是多条记录,都要映射pojo类型
⑤namespace,名称空间。为了对sql语句进行隔离。mapper开发dao方式,后面会写它的特殊作用
--------------------------------------------------------------------------------------------------------------------
示例: SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws IOException {
String resource = "config/SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test3() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Account> accounts=null;
accounts = sqlSession.selectList("account.selectName2", "付");
sqlSession.close();
for (Account account:accounts)
{
System.out.println(account);
}
}
--------------------------------------------------------------------------------------------------------------------
17.插入数据。配置如下:
<insert id="insertAccount" parameterType="com.fusong.POJO.Account">
INSERT into account VALUES (#{IdCard},#{money},#{name},#{sex})
</insert>
<insert id="insertAccount2" parameterType="com.fusong.POJO.Account">
INSERT into account (IdCard,money,name,sex) VALUES (#{IdCard},#{money},#{name},#{sex})
</insert>
①#{},当为简单属性传值时,里面的名字任意起。当为对象属性传值时。名字要与数据库字段的名字相同。否则会报如下异常:
There is no getter for property named 'IdCa' in 'class com.fusong.POJO.Account'
②paramterType:输入参数类型。应写成对象类型。com.fusong.POJO.Account
--------------------------------------------------------------------------------------------------------------------
程序如下;
@Test
public void test2() {
SqlSession session = sqlSessionFactory.openSession();
Account account = new Account();
account.setIdCard("456829645");
account.setMoney((double) 88888);
account.setName("段誉");
account.setSex("男");
session.insert("account.insertAccount", account);
session.commit();
session.close();
}
---------------------------------------------------------------------------------------------------------------------
总结:插入对象时,输入参数为对象。#{}命名要与数据库字段一致
更新操作:<update id="updateAccount" parameterType="com.fusong.POJO.Account">
UPDATE account SET name="乔峰" WHERE name=#{NAME }
</update>
---------------------------------------------------------------------------------------------------------------------
public void test1(){
SqlSession sqlSession=sqlSessionFactory.openSession();
Account account=new Account();
account.setName("付fu");
sqlSession.update("account.updateAccount",account.getName());
sqlSession.commit();
sqlSession.close();
}
---------------------------------------------------------------------------------------------------------------------
18.mysql的uuid机制生主键的好处:使用uuid生成主键的好处是不用考虑数据库移植后主键冲突问题
19.企业开发进行技术选型,考虑mybatis和hibernate适用场景:
mybatis与hibernate的重要区别:
①mybatis,入门简单。对sql优化和修改十分方便。适合开发需求变更频繁的系统
②hibernate入门门槛高,他是一个ORM(对象关系映射)框架,适合需求稳定的,对象数据类型稳定的项目
20.SqlMapConfig.xml,是mybatis唯一的配置文件,是全局配置文件。mapper.xml是以statement(把一个sql语句称为一个statement)。
21.mybatis开发dao方式:
①原始dao方式
需要写dao接口和实现类
②mapper(代理的方式)
程序员只需要写dao接口,dao接口实现对象由mybatis自动生成代理对象
*传统Dao的开发存在代码重复问题,如sqlSession.open(),sqlSession.close().
整个mybatis操作的代码模板重复
*dao的实现类中存在硬编码。“account.InsertAccount”
mapper代理的方式可以避免以上的问题:
要想让mybatis自动创建dao接口实现类的对象,必须遵循一些规则:
①mapper.xml中的namespace名称要与mapper接口中的类名称一致,目的是让
mapper.xml与mapper.java关联。我们只需要创建接口,而不需要创建实现类
②'id' as sql statement in mapper.xml equals method in class
<select id="selectNameBurriedly" parameterType="string" resultType="com.fusong.POJO.Account">
select * from account WHERE name LIKE "%${value}%"
</select>
③mapper.xml中的id,parameterType,resultType与接口中的一致
④注意创建代理对象的方法:
AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
注意:在用${}时,里面的参数也是有讲究的,传value没事,但是传别的值就会报错:
There is no getter for property named 'id' in 'class java.lang.String'
---------------------------------------------------------------------------------------------------------------------
AccountMapper.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 namespace="com.fusong.POJO.AccountDao">
<select id="selectByMoney" parameterType="double" resultType="com.fusong.POJO.Account">
select * from account WHERE money=#{id}
</select>
---------------------------------------------------------------------------------------------------------------------
只需要写一个接口:
public interface AccountDao {
public Account selectByMoney(Double money) throws Exception;
public List<Account> selectNameBurriedly(String name) throws Exception;
}
---------------------------------------------------------------------------------------------------------------------
public class AccountDaoTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
String source= "config/SqlMapConfig.xml";
InputStream inputStream= Resources.getResourceAsStream(source);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1(){
SqlSession sqlSession=sqlSessionFactory.openSession();
AccountDao accountDao= sqlSession.getMapper(AccountDao.class);
try {
Account account= accountDao.selectByMoney((double) 9999);
sqlSession.close();
System.out.println(account);
} catch (Exception e) {
e.printStackTrace();
}
}
}
---------------------------------------------------------------------------------------------------------------------
22.①SqlSession作用范围:
它是一个面向用户的接口,调用该接口的方法可操作数据库。由于sqlSession是线程不安全的
所以它的最佳应用范围在方法体内,被定义成局部变量
②SqlSessionFactory
正常开发时,以单例方式管理sqlSessionFactory,整个系统运行中sqlSessionFactory只有一个实例
,将来和spring整合后由spring以单例方式管理sqlSessionFactory
③sqlSessionFactoryBuilder
把它看作工具类,用来生成sqlSessionFactory实例
23.使用mapper代理方式开发,mapper接口方法输入参数只有一个,但是可扩展性没有问题,
因为dao层是通用的,可以通过扩展POJO将不同的参数传入进去
24.建议使用properties,但不要在<properties>里定义属性,只引用定义的properties文件中属性。
里面的key的定义有一些规则,最好按jdbc.name的方式定义
25.在接口方法里加throws Exception
楼主,我觉得必须要抛出的、而且实现接口的类也应该抛出自己的异常
26.ibatis我没用过,不过我对他有一些了解。我用过mybatis觉得他俩之间有些差别,但差别不是很大
。给我些许时间,我能胜任你们的工作
27.在SqlMapConfig.xml,settings全局参数配置,小心配置。mybatis没有这些性能参数,它会自动配置
28.定义别名:
<typeAlias type="com.fusong.POJO.Account" alias="Account"/>
使用别名:
<insert id="insertAccount2" parameterType="Account">
INSERT into account (IdCard,money,name,sex) VALUES (#{IdCard},#{money},#{name},#{sex})
</insert>
这里,type是别名映射的类型,alias是别名。
问题:如果用这种方法,我们需要为每一个类都取一个别名,繁琐。
这时我们需要考虑批量别名,定义:指定包路径,自动扫描包下面的POJO接口,并且自定自动定义别名
别名的默认为类名,首字母大小写都可以
<typeAliases><!--取别名-->
<package name="com.fusong.POJO"/>
</typeAliases>
29.typeHandlers,类型处理器将Java类型和jdbc类型进行映射
mybatis提供很多类型处理器,一般情况下够用了
30.mappers,在SqlMapConfig里的mappers。
之前通过resource引用mapper的映射文件,mapper.xml。<mapper resource="config\AccountMapper.xml"/>
之后我们通过class引用mapper的接口,该接口的全限定名。<mapper class="com.fusong.POJO.AccountDao"/>
需要xml文件和Java类名称一致,而且在同一目录下
而今改善方法,批量配置mapper.xml文件,和上面一样,写一个<package>标签,通过package自动扫描mapper的接口。
<mappers>
<!--<mapper resource="conAccountDao.xml.xml"/>-->
<!--<mapper class="com.fusong.POJO.AccountDao"/>-->
<mapper resource="config\account.xml"/>
<package name="com.fusong.POJO"/>
</mappers>
31.动态sql(重点):
where 1=1的解释:
①数据库在进行查询的时候,经常看到有的人使用where 1=1,主要是一些程序员的为了拼凑动态的sql语句,
如果使用不好会起到副作用的。是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。
②where 1=1 是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。
<sql id="MydefinedSql">
<if test="accountBoom!=null">
<if test="accountBoom.name!=null and accountBoom.name!=''">
AND name LIKE "%${accountBoom.name}%"
</if>
<if test="accountBoom.sex!=null and accountBoom.sex!=''">
AND sex = "${accountBoom.sex}"
</if>
</if>
</sql>
---------------------------------------------------------------------------------------------------------------------
<select id="selectNameBurriedly" parameterType="accountCustomer" resultType="Account">
select * from account
<where>
<include refid="MydefinedSql"/>
</where>
</select>
---------------------------------------------------------------------------------------------------------------------
@Test
public void test2() throws Exception {
SqlSession sqlSession=sqlSessionFactory.openSession();
AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
AccountCustomer accountCustomer=new AccountCustomer();
AccountBoom accountBoom=new AccountBoom();
accountBoom.setName("付");
//accountBoom.setSex("男");
accountCustomer.setAccountBoom(accountBoom);
List<Account> accounts=accountDao.selectNameBurriedly(accountCustomer);
sqlSession.close();
for (Account account1:accounts)
{
System.out.println(account1);
}
}
---------------------------------------------------------------------------------------------------------------------
32.ResultMap的配置:通过resultMap指定的POJO类型可与数据库字段映射,property是类型的属性值,column是数据库的字段名。
配置如下:
<resultMap id="MyResultMap" type="com.fusong.POJO.Account2">
<id property="UserId" column="IdCard"/>
<result property="Usermoney" column="money"/>
<result property="Username" column="name"/>
<result property="Usersex" column="sex"/>
</resultMap>
<select id="selectName" parameterType="string" resultMap="MyResultMap">
SELECT * FROM account WHERE NAME =#{VALUE }
</select>
33.商品订单数据模型
①重要字段:不能为空的字段为重要字段
②子表指向父表
③数据库级别的关系就是外键
34.webservice是远程调用的东西,?
35.缓存的意义:
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,
从缓存中,从而提高查询效率,解决了高并发系统的性能问题。
36.mybatis的一级缓存和二级缓存:(我们是不使用mybatis缓存的)
①mybatis一级缓存是一个sqlSession级别,sqlSession只能访问自己的一级缓存的数据。
第一次发出一个查询sql,sql查询结果写入sqlSession的一级缓存中。同一个sqlSession再次发出相同的sql,就从
一级缓存中读取。如果两次中间出现commit操作,sql查询语句的一级缓存将会清空,下次只能重新到数据库读取。然后
存入缓存。
一级缓存的配置:
mybatis默认支持一级缓存不需要配置。
注意:mybatis和spring整合后不支持一级缓存,整合后,spring按照mapper的模板去生成mapper代理对象。模板在最后
统一关闭sqlsession
②二级缓存是跨sqlSession,是mapper级别的缓存,对于mapper级别的缓存不同的sqlSession是可以共享的
二级缓存的范围是mapper级别(mapper同一个命名空间),mapper命名空间里的。mapper以命名空间为单位创建map数据结构
map<key,value>
二级缓存的配置:mybatis是没有默认的二级缓存的需要配置。
在SqlMapConfig.xml里配置:
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在mapper.xml里配置,表示使用缓存:
<cache/>
程序如下:
public void test2() {
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
List<Account> account = accountDao.selectNameBurriedly("付");
sqlSession.close();
System.out.println(account);
AccountDao accountDao2 = sqlSession2.getMapper(AccountDao.class);
List<Account> account2 = accountDao2.selectNameBurriedly("付");
sqlSession.close();
System.out.println(account2);
}
问题:这只是一个测试程序,当程序结束后释放内存所有的数据都清空了。该怎样从别的程序的
sqlSession里得到查询信息呢?
③每次查询,程序先看是否开启二级缓存,如果开启,从二级缓存的数据结构中取缓存数据
如果从二级缓存中没有取到,再从一级缓存中找。如果一级缓存也没有,则从数据库查询
④对于信息变化频率高的数据,需要禁用二级缓存,禁用方法:
在statement中设置useCache=false,可以禁用当前select语句的二级缓存,useCache默认情况下是TRUE
<select id="findOrderListResultMap" resultMap="OrderListMap" useCache="false">
⑤刷新缓存,flushcache,默认情况是true。
如果执行commit操作,对二级缓存进行刷新。
37.mybatis和ehcache缓存框架整合
mybatis二级缓存通过ehcache维护缓存数据。通过mybatis和ehcache框架进行整合,就可以把缓存数据的
管理托管给ehcache。
*实现思路:在mybatis中提供一个cache接口,只要实现cache接口就可以把缓存数据灵活的管理起来
38.缓存框架:redis,memacahed,ehcache
39.mybatis和spring整合:
①让spring管理SqlSessionFactory
②让spring管理对象和dao
*使用mybatis和spring整合,开发mapper代理以及原始dao接口
会自动开启事务,自动关闭sqlsession
③让spring管理数据源(数据库连接池)
40.整合后配置文件:
①applicationContext.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:annotation-config></context:annotation-config><!--XML与注解混搭的时候用的,纯注解可以不写-->
<!--加载配置文件-->
<context:property-placeholder location="config/jdbc.properties"></context:property-placeholder>
<!--配置数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.className}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--定义sqlSessionFactory属性-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!--mybatis配置文件-->
<property name="configLocation" value="config/SqlConfigMap.xml"/>
</bean>
<bean id="accountDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.fusong.POJO.AccountDao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!--<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">-->
<!--<property name="basePackage" value="com.fusong.POJO"/>-->
<!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>-->
<!--</bean>-->
</beans>
注意:使用MapperFactoryBean需要一个个配置mapper类。
使用MapperScannerConfigurer会自动配置包下的mapper类。
②SqlConfigMap.xml的配置如下:
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--批量取别名-->
<typeAliases>
<package name="com.fusong.POJO"/>
</typeAliases>
<!--批量配置mapper-->
<mappers>
<package name="com.fusong.POJO"/>
</mappers>
</configuration>
③mapper.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 namespace="com.fusong.POJO.AccountDao">
<resultMap id="ItemsResultMap" type="com.fusong.POJO.Items">
<id property="Userid" column="id"/>
<result property="UserName" column="name"/>
<result property="Myprice" column="price"/>
<result property="Mydetail" column="detail"/>
<result property="Mypic" column="pic"/>
<result property="Newdate" column="createtime"/>
</resultMap>
<select id="selectViaItems" parameterType="Items" resultMap="ItemsResultMap">
SELECT * FROM items WHERE name=#{UserName}
</select>
</mapper>
41.mybatis逆向工程:
什么是逆向工程:我们平时在使用Mabatis框架进行Web应用开发的过程中,需要根据数据库表编写对应的Pojo类和Mapper映射文件,而这个过程重复单一且浪费时间。基于此,MyBatis官方为了让开发者更加方便快捷地使用MYBatis框架而不必编写繁琐的Pojo类以及Mapper文件,提供了一个十分简洁的逆向工程的工具。
Mybatis官方提供了逆向工程,可以针对数据库的表自动生成对应的mybatis代码(mapper.java\mapper.xml\pojo类)有了这个工具可以大大简化我们持久层代码的编写,和写代码过程中出错的概率。
2.jdbc编程中的问题:企业开发中,根据项目大小,特点进行技术选型,jdbc也是技术选型的参考。
jdbc操作数据库效率比框架要高。
3.PreparedStatement是预编译的statement,通过statement发起数据库的操作。Preparedstatement,
可以防止sql注入,执行数据库效率高。通过PreparedStatement发送到数据库的sql语句,数据库会对
这些语句进行缓存。二次发送时,可以省略编译的步骤。
4.jdbc问题总结:
①数据库连接频繁的创建与关闭,极大浪费数据库资源。
*解决该问题可以用数据库连接池(c3p0)
②sql语句是硬性编码,硬性编码不利于系统维护。如果需求变更,需要修改sql,就需要修改Java代码
*将sql语句统一配置在文件中,修改sql不需要修改Java代码
③向PreparedStatement占位符设置参数存在硬编码(参数位置)问题
*将sql中的占位符配置在配置文件中
④遍历结果集存在硬编码问题
*自动进行sql查询结果向Java对象映射
5.mybatis架构:
①它有一个最基础的配置文件,SqlMapperConfig.xml.(全剧配置文件)。它的作用是加载mybatis的运行环境
它的作用是加载mybatis的运行环经所需要的东西,如数据源,事务
②mapper.xml(配置sql语句)
*mybatis的重点不是环境,而是sql语句,会写sql语句
6.SqlSessionFactory(会话工厂)的作用是创建SqlSession,sqlSession的作用是操作数据库
SqlSession是面向用户的接口,它里面的方法就是CRUD方法
7.内部并不是SqlSession干活,而是Executor,数据库操作的执行器。
Excutor也是一个接口,它有默认执行器和缓存执行器
8.MappedStatement(mybatis的封装对象),封装sql语句
9.mapped,mapping,映射。
10.log4j.properties 作用:① Log4j是Apache的一个开放源代码项目,通过使用Log4j,
我们可以控制日志信息输送的目的地是控制台、文件、GUI组件②通过定义每一条日志信息的级别,
我们能够更加细致地控制日志的生成过程
11.POJO:简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。
12.映射:在JavaBean类与数据库字段里,如果有想匹配的名称。数据库就会把字段的值赋给JavaBean类的属性
13.mapper.xml,命名方式:表明+mapper.xml
14.selectOne(String statement,Object obj),用于查找单条记录。否则会报这样的错误
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned
by selectOne(), but found: 2
selectList(String statement,Object obj).
15.占位符:①#{},表示一个占位符,向该占位符传参数时,mybatis会自动拼接。比如传入字符串,mybatis最终拼接好
的sql就是参数两边加单引号。
②${},表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中,缺点:因为是拼接串,不能防止sql注入
16.mybatis的配置:
①编写SqlMapConfig.xml:
--------------------------------------------------------------------------------------------------------------------
<!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"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/newstart"/>
<property name="username" value="root"/>
<property name="password" value="fusong"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="config\account.xml"/>
</mappers>
</configuration>
①当mybatis与spring结合使用时,<environments这个标签就废掉了。
②<mappers>标签是mybatis提供的,要加到<configuration>里,进行sql语句的管理。
--------------------------------------------------------------------------------------------------------------------
②编写account.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 namespace="account">
<select id="selectByMoney" parameterType="double" resultType="com.fusong.POJO.Account">
select * from account WHERE money=#{id}
</select>
<select id="selectName" parameterType="string" resultType="com.fusong.POJO.Account">
select * from account WHERE name LIKE #{id}
</select>
<select id="selectName2" parameterType="string" resultType="com.fusong.POJO.Account">
select * from account WHERE name LIKE "%${value}%"
</select>
</mapper>
①id="selectByMoney",这里的id看作具有一个唯一标识的statement。在后面程序里我们要找它。
②#{},表示一个占位符,当这里面传入简单类型的参数时,这里面的名称随意
③parameterType:输入参数的类型,通过#{}接收程序里输入的参数
④resultType:输出结果的类型,不管输出单条还是多条记录,都要映射pojo类型
⑤namespace,名称空间。为了对sql语句进行隔离。mapper开发dao方式,后面会写它的特殊作用
--------------------------------------------------------------------------------------------------------------------
示例: SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws IOException {
String resource = "config/SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test3() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Account> accounts=null;
accounts = sqlSession.selectList("account.selectName2", "付");
sqlSession.close();
for (Account account:accounts)
{
System.out.println(account);
}
}
--------------------------------------------------------------------------------------------------------------------
17.插入数据。配置如下:
<insert id="insertAccount" parameterType="com.fusong.POJO.Account">
INSERT into account VALUES (#{IdCard},#{money},#{name},#{sex})
</insert>
<insert id="insertAccount2" parameterType="com.fusong.POJO.Account">
INSERT into account (IdCard,money,name,sex) VALUES (#{IdCard},#{money},#{name},#{sex})
</insert>
①#{},当为简单属性传值时,里面的名字任意起。当为对象属性传值时。名字要与数据库字段的名字相同。否则会报如下异常:
There is no getter for property named 'IdCa' in 'class com.fusong.POJO.Account'
②paramterType:输入参数类型。应写成对象类型。com.fusong.POJO.Account
--------------------------------------------------------------------------------------------------------------------
程序如下;
@Test
public void test2() {
SqlSession session = sqlSessionFactory.openSession();
Account account = new Account();
account.setIdCard("456829645");
account.setMoney((double) 88888);
account.setName("段誉");
account.setSex("男");
session.insert("account.insertAccount", account);
session.commit();
session.close();
}
---------------------------------------------------------------------------------------------------------------------
总结:插入对象时,输入参数为对象。#{}命名要与数据库字段一致
更新操作:<update id="updateAccount" parameterType="com.fusong.POJO.Account">
UPDATE account SET name="乔峰" WHERE name=#{NAME }
</update>
---------------------------------------------------------------------------------------------------------------------
public void test1(){
SqlSession sqlSession=sqlSessionFactory.openSession();
Account account=new Account();
account.setName("付fu");
sqlSession.update("account.updateAccount",account.getName());
sqlSession.commit();
sqlSession.close();
}
---------------------------------------------------------------------------------------------------------------------
18.mysql的uuid机制生主键的好处:使用uuid生成主键的好处是不用考虑数据库移植后主键冲突问题
19.企业开发进行技术选型,考虑mybatis和hibernate适用场景:
mybatis与hibernate的重要区别:
①mybatis,入门简单。对sql优化和修改十分方便。适合开发需求变更频繁的系统
②hibernate入门门槛高,他是一个ORM(对象关系映射)框架,适合需求稳定的,对象数据类型稳定的项目
20.SqlMapConfig.xml,是mybatis唯一的配置文件,是全局配置文件。mapper.xml是以statement(把一个sql语句称为一个statement)。
21.mybatis开发dao方式:
①原始dao方式
需要写dao接口和实现类
②mapper(代理的方式)
程序员只需要写dao接口,dao接口实现对象由mybatis自动生成代理对象
*传统Dao的开发存在代码重复问题,如sqlSession.open(),sqlSession.close().
整个mybatis操作的代码模板重复
*dao的实现类中存在硬编码。“account.InsertAccount”
mapper代理的方式可以避免以上的问题:
要想让mybatis自动创建dao接口实现类的对象,必须遵循一些规则:
①mapper.xml中的namespace名称要与mapper接口中的类名称一致,目的是让
mapper.xml与mapper.java关联。我们只需要创建接口,而不需要创建实现类
②'id' as sql statement in mapper.xml equals method in class
<select id="selectNameBurriedly" parameterType="string" resultType="com.fusong.POJO.Account">
select * from account WHERE name LIKE "%${value}%"
</select>
③mapper.xml中的id,parameterType,resultType与接口中的一致
④注意创建代理对象的方法:
AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
注意:在用${}时,里面的参数也是有讲究的,传value没事,但是传别的值就会报错:
There is no getter for property named 'id' in 'class java.lang.String'
---------------------------------------------------------------------------------------------------------------------
AccountMapper.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 namespace="com.fusong.POJO.AccountDao">
<select id="selectByMoney" parameterType="double" resultType="com.fusong.POJO.Account">
select * from account WHERE money=#{id}
</select>
---------------------------------------------------------------------------------------------------------------------
只需要写一个接口:
public interface AccountDao {
public Account selectByMoney(Double money) throws Exception;
public List<Account> selectNameBurriedly(String name) throws Exception;
}
---------------------------------------------------------------------------------------------------------------------
public class AccountDaoTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
String source= "config/SqlMapConfig.xml";
InputStream inputStream= Resources.getResourceAsStream(source);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1(){
SqlSession sqlSession=sqlSessionFactory.openSession();
AccountDao accountDao= sqlSession.getMapper(AccountDao.class);
try {
Account account= accountDao.selectByMoney((double) 9999);
sqlSession.close();
System.out.println(account);
} catch (Exception e) {
e.printStackTrace();
}
}
}
---------------------------------------------------------------------------------------------------------------------
22.①SqlSession作用范围:
它是一个面向用户的接口,调用该接口的方法可操作数据库。由于sqlSession是线程不安全的
所以它的最佳应用范围在方法体内,被定义成局部变量
②SqlSessionFactory
正常开发时,以单例方式管理sqlSessionFactory,整个系统运行中sqlSessionFactory只有一个实例
,将来和spring整合后由spring以单例方式管理sqlSessionFactory
③sqlSessionFactoryBuilder
把它看作工具类,用来生成sqlSessionFactory实例
23.使用mapper代理方式开发,mapper接口方法输入参数只有一个,但是可扩展性没有问题,
因为dao层是通用的,可以通过扩展POJO将不同的参数传入进去
24.建议使用properties,但不要在<properties>里定义属性,只引用定义的properties文件中属性。
里面的key的定义有一些规则,最好按jdbc.name的方式定义
25.在接口方法里加throws Exception
楼主,我觉得必须要抛出的、而且实现接口的类也应该抛出自己的异常
26.ibatis我没用过,不过我对他有一些了解。我用过mybatis觉得他俩之间有些差别,但差别不是很大
。给我些许时间,我能胜任你们的工作
27.在SqlMapConfig.xml,settings全局参数配置,小心配置。mybatis没有这些性能参数,它会自动配置
28.定义别名:
<typeAlias type="com.fusong.POJO.Account" alias="Account"/>
使用别名:
<insert id="insertAccount2" parameterType="Account">
INSERT into account (IdCard,money,name,sex) VALUES (#{IdCard},#{money},#{name},#{sex})
</insert>
这里,type是别名映射的类型,alias是别名。
问题:如果用这种方法,我们需要为每一个类都取一个别名,繁琐。
这时我们需要考虑批量别名,定义:指定包路径,自动扫描包下面的POJO接口,并且自定自动定义别名
别名的默认为类名,首字母大小写都可以
<typeAliases><!--取别名-->
<package name="com.fusong.POJO"/>
</typeAliases>
29.typeHandlers,类型处理器将Java类型和jdbc类型进行映射
mybatis提供很多类型处理器,一般情况下够用了
30.mappers,在SqlMapConfig里的mappers。
之前通过resource引用mapper的映射文件,mapper.xml。<mapper resource="config\AccountMapper.xml"/>
之后我们通过class引用mapper的接口,该接口的全限定名。<mapper class="com.fusong.POJO.AccountDao"/>
需要xml文件和Java类名称一致,而且在同一目录下
而今改善方法,批量配置mapper.xml文件,和上面一样,写一个<package>标签,通过package自动扫描mapper的接口。
<mappers>
<!--<mapper resource="conAccountDao.xml.xml"/>-->
<!--<mapper class="com.fusong.POJO.AccountDao"/>-->
<mapper resource="config\account.xml"/>
<package name="com.fusong.POJO"/>
</mappers>
31.动态sql(重点):
where 1=1的解释:
①数据库在进行查询的时候,经常看到有的人使用where 1=1,主要是一些程序员的为了拼凑动态的sql语句,
如果使用不好会起到副作用的。是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。
②where 1=1 是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。
<sql id="MydefinedSql">
<if test="accountBoom!=null">
<if test="accountBoom.name!=null and accountBoom.name!=''">
AND name LIKE "%${accountBoom.name}%"
</if>
<if test="accountBoom.sex!=null and accountBoom.sex!=''">
AND sex = "${accountBoom.sex}"
</if>
</if>
</sql>
---------------------------------------------------------------------------------------------------------------------
<select id="selectNameBurriedly" parameterType="accountCustomer" resultType="Account">
select * from account
<where>
<include refid="MydefinedSql"/>
</where>
</select>
---------------------------------------------------------------------------------------------------------------------
@Test
public void test2() throws Exception {
SqlSession sqlSession=sqlSessionFactory.openSession();
AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
AccountCustomer accountCustomer=new AccountCustomer();
AccountBoom accountBoom=new AccountBoom();
accountBoom.setName("付");
//accountBoom.setSex("男");
accountCustomer.setAccountBoom(accountBoom);
List<Account> accounts=accountDao.selectNameBurriedly(accountCustomer);
sqlSession.close();
for (Account account1:accounts)
{
System.out.println(account1);
}
}
---------------------------------------------------------------------------------------------------------------------
32.ResultMap的配置:通过resultMap指定的POJO类型可与数据库字段映射,property是类型的属性值,column是数据库的字段名。
配置如下:
<resultMap id="MyResultMap" type="com.fusong.POJO.Account2">
<id property="UserId" column="IdCard"/>
<result property="Usermoney" column="money"/>
<result property="Username" column="name"/>
<result property="Usersex" column="sex"/>
</resultMap>
<select id="selectName" parameterType="string" resultMap="MyResultMap">
SELECT * FROM account WHERE NAME =#{VALUE }
</select>
33.商品订单数据模型
①重要字段:不能为空的字段为重要字段
②子表指向父表
③数据库级别的关系就是外键
34.webservice是远程调用的东西,?
35.缓存的意义:
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,
从缓存中,从而提高查询效率,解决了高并发系统的性能问题。
36.mybatis的一级缓存和二级缓存:(我们是不使用mybatis缓存的)
①mybatis一级缓存是一个sqlSession级别,sqlSession只能访问自己的一级缓存的数据。
第一次发出一个查询sql,sql查询结果写入sqlSession的一级缓存中。同一个sqlSession再次发出相同的sql,就从
一级缓存中读取。如果两次中间出现commit操作,sql查询语句的一级缓存将会清空,下次只能重新到数据库读取。然后
存入缓存。
一级缓存的配置:
mybatis默认支持一级缓存不需要配置。
注意:mybatis和spring整合后不支持一级缓存,整合后,spring按照mapper的模板去生成mapper代理对象。模板在最后
统一关闭sqlsession
②二级缓存是跨sqlSession,是mapper级别的缓存,对于mapper级别的缓存不同的sqlSession是可以共享的
二级缓存的范围是mapper级别(mapper同一个命名空间),mapper命名空间里的。mapper以命名空间为单位创建map数据结构
map<key,value>
二级缓存的配置:mybatis是没有默认的二级缓存的需要配置。
在SqlMapConfig.xml里配置:
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在mapper.xml里配置,表示使用缓存:
<cache/>
程序如下:
public void test2() {
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
List<Account> account = accountDao.selectNameBurriedly("付");
sqlSession.close();
System.out.println(account);
AccountDao accountDao2 = sqlSession2.getMapper(AccountDao.class);
List<Account> account2 = accountDao2.selectNameBurriedly("付");
sqlSession.close();
System.out.println(account2);
}
问题:这只是一个测试程序,当程序结束后释放内存所有的数据都清空了。该怎样从别的程序的
sqlSession里得到查询信息呢?
③每次查询,程序先看是否开启二级缓存,如果开启,从二级缓存的数据结构中取缓存数据
如果从二级缓存中没有取到,再从一级缓存中找。如果一级缓存也没有,则从数据库查询
④对于信息变化频率高的数据,需要禁用二级缓存,禁用方法:
在statement中设置useCache=false,可以禁用当前select语句的二级缓存,useCache默认情况下是TRUE
<select id="findOrderListResultMap" resultMap="OrderListMap" useCache="false">
⑤刷新缓存,flushcache,默认情况是true。
如果执行commit操作,对二级缓存进行刷新。
37.mybatis和ehcache缓存框架整合
mybatis二级缓存通过ehcache维护缓存数据。通过mybatis和ehcache框架进行整合,就可以把缓存数据的
管理托管给ehcache。
*实现思路:在mybatis中提供一个cache接口,只要实现cache接口就可以把缓存数据灵活的管理起来
38.缓存框架:redis,memacahed,ehcache
39.mybatis和spring整合:
①让spring管理SqlSessionFactory
②让spring管理对象和dao
*使用mybatis和spring整合,开发mapper代理以及原始dao接口
会自动开启事务,自动关闭sqlsession
③让spring管理数据源(数据库连接池)
40.整合后配置文件:
①applicationContext.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:annotation-config></context:annotation-config><!--XML与注解混搭的时候用的,纯注解可以不写-->
<!--加载配置文件-->
<context:property-placeholder location="config/jdbc.properties"></context:property-placeholder>
<!--配置数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.className}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--定义sqlSessionFactory属性-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!--mybatis配置文件-->
<property name="configLocation" value="config/SqlConfigMap.xml"/>
</bean>
<bean id="accountDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.fusong.POJO.AccountDao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!--<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">-->
<!--<property name="basePackage" value="com.fusong.POJO"/>-->
<!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>-->
<!--</bean>-->
</beans>
注意:使用MapperFactoryBean需要一个个配置mapper类。
使用MapperScannerConfigurer会自动配置包下的mapper类。
②SqlConfigMap.xml的配置如下:
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--批量取别名-->
<typeAliases>
<package name="com.fusong.POJO"/>
</typeAliases>
<!--批量配置mapper-->
<mappers>
<package name="com.fusong.POJO"/>
</mappers>
</configuration>
③mapper.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 namespace="com.fusong.POJO.AccountDao">
<resultMap id="ItemsResultMap" type="com.fusong.POJO.Items">
<id property="Userid" column="id"/>
<result property="UserName" column="name"/>
<result property="Myprice" column="price"/>
<result property="Mydetail" column="detail"/>
<result property="Mypic" column="pic"/>
<result property="Newdate" column="createtime"/>
</resultMap>
<select id="selectViaItems" parameterType="Items" resultMap="ItemsResultMap">
SELECT * FROM items WHERE name=#{UserName}
</select>
</mapper>
41.mybatis逆向工程:
什么是逆向工程:我们平时在使用Mabatis框架进行Web应用开发的过程中,需要根据数据库表编写对应的Pojo类和Mapper映射文件,而这个过程重复单一且浪费时间。基于此,MyBatis官方为了让开发者更加方便快捷地使用MYBatis框架而不必编写繁琐的Pojo类以及Mapper文件,提供了一个十分简洁的逆向工程的工具。
Mybatis官方提供了逆向工程,可以针对数据库的表自动生成对应的mybatis代码(mapper.java\mapper.xml\pojo类)有了这个工具可以大大简化我们持久层代码的编写,和写代码过程中出错的概率。