原生jdbc
sql语句
create table user(
id int primary key auto_increment,
username varchar(32) not null,
sex char(1) default null,
birthday date default null,
address varchar(256) default null
);
insert into user values (null,'jack','M','2019-9-9','Beijing');
insert into user values (null,'rose','F','2018-8-9','Fijian');
insert into user values (null,'jhon','M','2019-10-9','Shenzhen');
pojo类
import java.util.Date;
public class User {
private int id;
private String username;
private String sex;//数据库用char?
private Date birthday;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
", address='" + address + '\'' +
'}';
}
}
查询数据库
import com.ahu.pojo.User;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* 原始jdbc问题:维护性差,扩展性差,出现问题,修改源码
*
* 代码量大
* 频繁连接,释放数据库资源,降低系统性能
* 引入连接池
*
* 数据库驱动类 ,连接四大信息
* 写配置文件
*
* SQL语句硬编码,SQL语句写死了
* SQL语句中的?占位符
* Apache DbUtils
*
* 封装数据表结果集代码,硬编码
* 框架:整合最基本的代码
* 连接数据库,执行SQL语句,封装结果集合,仅需要提供SQL语句
*/
public class jdbcDemo {
public static void main(String[] args) throws Exception {
//注册驱动程序
Class.forName("com.mysql.jdbc.Driver");
//获取链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3305/mybatis","root","ahulml005");
//查询数据库
PreparedStatement pstmt = conn.prepareStatement("select * from user");
ResultSet rs = pstmt.executeQuery();
List<User> list = new ArrayList<User>();
while(rs.next()){
int id = rs.getInt("id");
String username = rs.getString("username");
String sex = rs.getString("sex");
Date birthday = rs.getDate("birthday");
String address = rs.getString("address");
User user = new User();
user.setId(id);
user.setUsername(username);
user.setSex(sex);
user.setBirthday(birthday);
user.setAddress(address);
list.add(user);
}
rs.close();
pstmt.close();
conn.close();
for (User user : list) {
System.out.println(user);
}
}
}
mybatis框架
- Mybatis最大的特点是把Sql语句写在XML配置文件当中。而且Mybatis执行完Sql语句之后可以以对象形式返回(POJO/POJO集合等)。
- Mybatis是一个实现了ORM思想的持久层框架。
- ORM:Object/Relation Mapping 对象/关系映射。
- ORM思想:将数据库中的关系数据表映射为JAVA中的对象,把对数据表的操作转换为对对象的操作,实现面向对象编程。
使用步骤
- 导入jar包
- 配置xml(sql语句写在xml中,返回pojo对象或者集合)
- 调用API(接口SqlSession,使用工厂类SqlSessionFactory获取实现类,而不是自己编写,有利于扩展性)
快速入门
- SqlMapConfig.xml
<?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" 默认,值=development 开发环境
environment 运行环境,配置一个
id="development" id唯一性的属性 值=id="development" 开发环境
id="product" 生产环境
id="test" 测试环境
-->
<environments default="development">
<environment id="development">
<!--
transactionManager 事务管理配置
type="JDBC" 使用的是最原始的JDBC的事务处理机制
type="MANAGERED" 不管理事务
-->
<transactionManager type="JDBC" />
<!--
dataSource 配置数据源,连接池
type="POOLED" 使用连接池
MyBatis自带连接池 (type=""UNPOOLED)
-->
<dataSource type="POOLED">
<!--配置的是,数据库连接四大信息-->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3305/mybatis?characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="ahulml005" />
</dataSource>
</environment>
<!--
<environment id="produce">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatisProduce?characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatisTest?characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>-->
</environments>
<!--
配置的是映射关系 ORM Java对象和数据表
-->
<mappers>
<!--
单独的映射关系
resource资源,映射文件的路径
UserMapper.xml 配置的是数据表user的SQL语句,每个xml文件对应每一张表,对应一个namespace
命名空间是唯一的,不同的表的xml应该命名不同
-->
<mapper resource="UserMapper.xml" />
<!--<mapper resource="StudentMapper.xml"/>-->
</mappers>
</configuration>
- UserMapper.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 命名空间,属性值要求唯一性
整个的SQL语句配置文件
-->
<mapper namespace="test">
<!--
配置删除数据,标签delete
-->
<delete id="deleteUserById" parameterType="Integer">
delete from user where id = #{id}
</delete>
<!--
配置更新数据,标签update
-->
<update id="updateUserById" parameterType="com.ahu.pojo.User">
update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}
</update>
<!--
配置新增数据,标签insert
新增数据,SQL语句中,一定会有很多参数
参数封装在pojo对象,配置的时候,标签属性parameterType
SQL语句中参数的数据类型是数据库表的列名
pojo对象User,封装了所有的数据
增删改,结果是行数,int类型,不要配置resultType
新增操作:insert标签中,子标签 <selectKey> 获取上一次新增主键值
属性:
order="after或者before" 获取主键,是在SQL语句之前,还是之后执行
resultType 获取主键的结果数据类型
keyProperty 属性,查询后的值放那里 pojo对象的属性中
-->
<insert id="saveUser" parameterType="com.ahu.pojo.User">
<!--
传递的参数是对象 pojo
#{pojo对象的属性名!!}
-->
insert into user values (null,#{username},#{sex},#{birthday},#{address})
<selectKey order="AFTER" resultType="Integer" keyProperty="id">
SELECT LAST_INSERT_ID ()
</selectKey>
</insert>
<!-- selectKey自动封装为pojo对象的id值,只有连接有效-->
<!--
select 标签,配置的是查询语句
id 属性,唯一性,在当前文件中唯一 ,属性值 queryList
框架执行SQL语句: namespace+"."+queryList 确定SQL语句
resultType: 查询的结果集,是pojo对象
标签体: 是SQL语句
-->
<select id="queryList" resultType="com.ahu.pojo.User">
select * from user
</select>
<!--
配置,数据表user模糊查询
用户名模糊查询
SQL语句参数
${参数名} 写参数名字,固定写为value
#{} ${} 获取参数的区别
select * from user where username like #{value}
select * from user where username like ? '%王%'
参数编译为 ? 传递的实际参数 "'%王%'" 替换到?占位符
框架底层使用的JDBC中的接口 PreparedStatement
select * from user where username like ${value}
select * from user where username like '%王%'
直接拼接了字符串!!
${} 适合于特殊场景, SQL语句中的参数是 列名或者表名的时候
select * from user order by
-->
<select id="queryUserByUserName" resultType="com.ahu.pojo.User" parameterType="String">
select * from user where username like #{value}
</select>
<!--
配置,主键查询的SQL语句 ,标签 select
id具有唯一性
查询是有结果集
标签中属性 resultType:配置结果集的类型
SQL语句有参数的
标签中属性 parameterType: SQL语句的参数类型
-->
<select id="queryUserById" resultType="com.ahu.pojo.User" parameterType="Integer">
<!--
SQL语句
MyBatis配置SQL语句,参数不能写问号
取参数 #{参数名}
参数名,如果只有一个参数,基本类型及其包装类和String,任意
-->
select * from user where id = #{id}
</select>
<!-- <select id="queryUserById" resultType="com.ahu.pojo.User" parameterType="Integer">-->
<!-- select * from user where id = #{id}-->
<!-- </select>-->
</mapper>
- QuickStart
import com.ahu.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybatisCRUD {
private SqlSessionFactory sqlSessionFactory;
@Before
public void before() throws IOException {
//创建sqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//Mybatis提供Resource静态类方法getResourceAsStream(),底层封装的是类加载器
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");//自动从源码src目录下读取文件
sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
}
/**
* 根据主键查询表user
*/
@Test
public void testQueryUserByid() throws IOException {
// //创建sqlSessionFactoryBuilder对象
// SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// //Mybatis提供Resource静态类方法getResourceAsStream(),底层封装的是类加载器
// InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");//自动从源码src目录下读取文件
// SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql语句,通过namespace+id锁定sql语句
User user = sqlSession.selectOne("test.queryUserById",3);
System.out.println(user);
sqlSession.close();
}
/**
* 框架:查询数据表user,根据用户名模糊查询
* 大量的重复性代码: 代码坏味道
* 共性抽取:
* 目的: SqlSession接口,执行SQL语句
* 每个功能不同的,SqlSession接口不能抽取?
*
* 读取配置文件可以抽取
* SqlSessionFactory sqlSessionFactory 创建SqlSession接口对象,可以抽取
* 工厂对象,提升为成员变量
*
* ${}和#{}的区别
*
* select * from user where username like ${value}
* ${} 拼接字符串Preparing: select * from user where username like '%ja%'
*
*
* #{} 底层框架使用preStatement,Preparing: select * from user where username like ? ,参数编译为?,
* 使用传递的参数替换?
*
* ${} 适合于特殊场景, SQL语句中的参数是 列名或者表名的时候
* select * from user order by
*/
@Test
public void testQueryUserByUserName(){
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("test.queryUserByUserName", "%ja%");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
/**
* 新增用户,回传id
*/
@Test
public void testSaveUser(){
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("孙尚香");
user.setSex("F");
user.setBirthday(new Date());
user.setAddress("东吴");
//mybatis默认需要提交事务
int update = sqlSession.insert("test.saveUser",user);
sqlSession.commit();
System.out.println(user);
System.out.println(update);
}
/**
* 更新用户
*/
@Test
public void testUpdateUser(){
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(6);
user.setUsername("阿斗");
user.setSex("M");
user.setAddress("蜀地");
user.setBirthday(new Date());
int row = sqlSession.update("test.updateUserById",user);
sqlSession.commit();
System.out.println(row);
}
/**
* 删除用户
*/
@Test
public void testDeleteUser(){
SqlSession sqlSession = sqlSessionFactory.openSession();
int row = sqlSession.delete("test.deleteUserById",11);
sqlSession.commit();
System.out.println(row);
}
}
日志记录
使用log4j,使用导入jar包和配置文件即可
#log4j日志级别如下:
#A:off 最高等级,用于关闭所有日志记录。
#B:fatal 指出每个严重的错误事件将会导致应用程序的退出。
#C:error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
#D:warn 表明会出现潜在的错误情形。
#E:info 一般和在粗粒度级别上,强调应用程序的运行全程。(运行时)
#F:debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
#G:all 最低等级,用于打开所有日志记录。
#但log4j只建议使用4个级别,优先级从高到低分别是:
#error>warn>info>debug
#日志根配置,记录级别,第二个参数起是日志输出位置
log4j.rootLogger =debug,systemOut
#输出到控制台
log4j.appender.systemOut = org.apache.log4j.ConsoleAppender
log4j.appender.systemOut.layout = org.apache.log4j.PatternLayout
#日志记录格式
log4j.appender.systemOut.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
#输出到控制台
log4j.appender.systemOut.Target = System.out
#输出到文件
log4j.appender.logFile = org.apache.log4j.FileAppender
log4j.appender.logFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.logFile.File = E:/log/log4j.log
log4j.appender.logFile.Encoding = UTF-8
#将日志输记录到MySQL数据库
#log4j.appender.logDB = org.apache.log4j.jdbc.JDBCAppender
#log4j.appender.logDB.layout = org.apache.log4j.PatternLayout
#log4j.appender.logDB.Driver = com.mysql.jdbc.Driver
#log4j.appender.logDB.URL = jdbc:mysql://localhost:3306/log4j?characterEncoding=utf-8
#log4j.appender.logDB.User = root
#log4j.appender.logDB.Password = root
#log4j.appender.logDB.Sql = INSERT INTO t_log4j(project_name,create_date,level,category,file_name,thread_name,line,all_category,message)values('mybatis','%d{yyyy-MM-ddHH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
#若出现问题:Log4j: ERROR Failed to load driver, java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
#解决方法:将log4j.properties 中每行后面的空格都删除就解决了.