文章目录
- 6、生命周期和作用域
- 5、解决属性名和字段名不一致的问题
- 1、问题
- 2、resultMap
- 6、日志
- 6.1、日志工厂
- 6.2、Log4j
- 7、分页
- 8、使用注解开发
- 8.2、CRUD
- 关于@Param()注解
- 9、Lombok
- 10、多对一
6、生命周期和作用域
生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder:
一旦创建了SqlSessionFactory,就不需要它了
局部变量
SqlSessionFactory:
○说白了就是可以想象为:数据库连接池。
○一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
○因此SqlSessionFactory的最佳作用域是应用作用域(程序开始它开始,程序结束它结束)。
○最简单的就是使用单例模式或者静态单例模式。
SqlSession:
○连接到连接池的一个请求。
○SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
○用完之后需要赶紧关闭,否则资源被占用。
这里面每一个Mapper,就代表一个具体的业务。
5、解决属性名和字段名不一致的问题
1、问题
数据库中的字段
新建一个项目,拷贝到之前的,测试实体类字段不一致的情况。
public class User {
private int id;
private String name;
private String password;
}
测试出现问题:
//select * from mybatis.user where id=#{id}
//类型处理器
//select id,name,pwd from mybatis.user where id=#{id}
解决方法:
○起别名
<select id="getUserById" parameterType="int" resultType="user">
SELECT id,name,pwd AS password FROM mybatis.user WHERE id=#{id}
</select>
2、resultMap
结果集映射
id name pwd
id name password
<!--结果集映射-->
<resultMap id="UserMap" type="User">
<!--column数据库中的字段,property实体类中的属性-->
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="password" column="pwd"/>
</resultMap>
<select id="getUserById" resultMap="UserMap">
SELECT * FROM mybatis.user WHERE id=#{id}
</select>
○resultMap元素是Mybatis中最重要最强大的元素
○ResultMap的设计思想是,对于简单的语句根本不需要配置显示的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。
○ResultMap最优秀的地方在于,虽然你已经对它相当了解了,但是根本不需要显式地用到它们。
6、日志
6.1、日志工厂
如果一个数据库操作,出现了异常,我们需要排错。日志就是最好的助手。
曾经:sout、debug
现在:日志工厂
○SLF4J
○LOG4J【掌握】
○LOG4J2
○JDK_LOGGING
○COMMONS_LOGGING
○STDOUT_LOGGING【掌握】
○NO_LOGGING
<settings>
<!--标准的日志工厂实现-->
<setting name="logImp1" value="STDOUT_LOGGING"/>
</settings>
6.2、Log4j
什么是Log4j?
○Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息传送的目的地是控制台、文件、GUI组件。
○我们也可以控制每一条日志的输出格式。
○通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
○通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
1.先导入log4j
<!--http://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2.log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码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.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/muzi.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.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
3.配置log4j为日志的实现
<settings>
<setting name="logImpl" value=""/>
</settings>
4.Log4j的使用,直接测试运行刚才的查询
简单使用
1.在要使用Log4j的类中,导入import org.apache.log4j.Logger;
2.日志对象,参数为当前类的class
Logger logger = Logger.getLogger(UserMapperTest.class);
3.日志级别
logger.info("info:进入了testLog4j");
logger.debug("debug:进入了testLog4j");
logger.error("error:进入了testLog4j");
7、分页
思考:为什么要分页?
○减少数据的处理量
select * from user limit startIndex,pageSize;
使用Mybatis实现分页,核心SQL
1.接口
//分页List<User> getUserByLimit(Map<String,Integer> map);
2.Mapper
<!--分页-->
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
SELECT * FROM mybatis.user limit #{startIndex},#{pageSize}
</select>
3.测试
@Testpublic void getUserByLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,Integer> map=new HashMap<String, Integer>();
map.put("startIndex",1);
map.put("pageSize",2);
List<User> list = mapper.getUserByLimit(map);
for(User user:list){
System.out.println(user);
}
sqlSession.close();
}
8、使用注解开发
8.1、使用注解开发
1.注解在接口上实现
@Select("select * from user")
List<User> getUsers();
2.需要在核心配置文件绑定接口
<!--绑定接口-->
<mappers>
<mapper class="com.muzi.dao.UserMapper"/>
</mappers>
3.测试
@Testpublic 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详细的执行流程
8.2、CRUD
我们可以在工具类创建的时候实现自动提交事务。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();//工厂来打开连接,返回一个数据库连接
}
编写接口,增加注解
public interface UserMapper {
@Select("select * from user")
List<User> getUsers();
@Select("select * from user where id=#{id}")
User getUserById(@Param("id") int id);//基本类型的全部加上,引用类型不用加
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
int addUser(User user);
@Update("update user set name=#{name},pwd=#{password} where id=#{id}")
int updateUser(User user);
@Delete("delete from user where id=#{id}")
int delete(@Param("id") 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 userById = mapper.getUserById(1);
System.out.println(userById);*/
// mapper.addUser(new User(4,"hello","123456"));
// mapper.updateUser(new User(4,"to","456"));
mapper.delete(4);
sqlSession.close();
}
注意:我们必须要将接口注册绑定到我们的核心配置文件中。
关于@Param()注解
○基本类型的参数或者String类型,需要加上
○引用类型不需要加
○如果只有一个基本类型的话,可以忽略,但是建议都加上。
○我们在SQL中引用的就是我们这里的@Param(“uid”)中设定的属性名。
9、Lombok
使用步骤:
1.在IDEA中安装Lombok插件
2.在项目中导入lombok的jar包
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
3.在实体来上加注解
10、多对一
多对一:
○多个学生,对应一个老师
○对于学生这边而言,关联…多个学生,关联一个老师
○对于老师而言,集合,一个老师,有很多学生【一对多】
SQL:
CREATE TABLE `teacher`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY(`id`)
)
ALTER TABLE `teacher` CHANGE `name` `name` VARCHAR( 30 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
INSERT INTO teacher(`id`,`name`) VALUES(1,'秦老师');
CREATE TABLE `student`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY(`id`),
KEY `fktid`(`tid`),
CONSTRAINT `fktid` FOREIGN KEY(`tid`) REFERENCES `teacher`(`id`)
)
ALTER TABLE `student` CHANGE `name` `name` VARCHAR( 30 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('1','小明','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('2','小红','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('3','小张','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('4','小李','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('5','小王','1');