Dao接口
package com.bjpowernode.dao;
import com.bjpowernode.domain.Student;
import java.util.List;
//接口操作student表
public interface StudentDao {
//查询student表的所有的数据
public List<Student> selectStudents();
//插入方法
//参数: student ,表示要插入到数据库的数据
//返回值: int , 表示执行insert操作后的 影响数据库的行数
public int insertStudent(Student student);
}
SQL映射文件配置
<?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.bjpowernode.dao.StudentDao">
<!--
select:表示查询操作。
id: 你要执行的sql语法的唯一标识, mybatis会使用这个id的值来找到要执行的sql语句
可以自定义,但是要求你使用接口中的方法名称。
resultType:表示结果类型的, 是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
值写的类型的全限定名称
-->
<select id="selectStudents" resultType="com.bjpowernode.domain.Student" >
select id,name,email,age from student order by id
</select>
<!--插入操作-->
<insert id="insertStudent">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
</mapper>
<!--
sql映射文件(sql mapper): 写sql语句的, mybatis会执行这些sql
1.指定约束文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd是约束文件的名称, 扩展名是dtd的。
2.约束文件作用: 限制,检查在当前文件中出现的标签,属性必须符合mybatis的要求。
3.mapper 是当前文件的根标签,必须的。
namespace:叫做命名空间,唯一值的, 可以是自定义的字符串。
要求你使用dao接口的全限定名称。
4.在当前文件中,可以使用特定的标签,表示数据库的特定操作。
<select>:表示执行查询,select语句
<update>:表示更新数据库的操作, 就是在<update>标签中 写的是update sql语句
<insert>:表示插入, 放的是insert语句
<delete>:表示删除, 执行的delete语句
-->
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>
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志,方便调试-->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!--
logIpml:控制日志
STAOUT_LOGGING:把日志输出到控制台
-->
</settings>
<!--环境配置: 数据库的连接信息
default:必须和某个environment的id值一样。
告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库
便于实际开发时切换数据库
-->
<environments default="mydev">
<!-- environment : 一个数据库信息的配置, 环境
id:一个唯一值,自定义,表示环境的名称。
-->
<environment id="mydev">
<!--
transactionManager :mybatis的事务类型
type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,连接数据库的
type:表示数据源的类型, POOLED表示使用连接池
-->
<dataSource type="POOLED">
<!--
driver, user, username, password 是固定的,不能自定义。
-->
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="123456"/>
</dataSource>
</environment>
<!--表示线上的数据库,是项目真实使用的库-->
<environment id="online">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/onlinedb"/>
<property name="username" value="root"/>
<property name="password" value="fhwertwr"/>
</dataSource>
</environment>
</environments>
<!-- 指定sql mapper(sql映射文件)的位置-->
<mappers>
<!--一个mapper标签指定一个文件的位置。
从类路径开始的路径信息。 target/clasess(类路径)
-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
</mappers>
</configuration>
<!--
mybatis的主配置文件: 主要定义了数据库的配置信息, sql映射文件的位置
1. 约束文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
mybatis-3-config.dtd:约束文件的名称
2. configuration 根标签。
-->
你只要读取到了主配置,就能知道数据库的连接信息,也能知道sql映射文件。所以我们在使用的时候只需要读主配置文件就行了。读到sql映射文件也就能读到要执行的sql语句了。最后它会通过sql映射文件的标识和具体sql语句的标识来找到需要执行的sql文件。
测试Mybatis
package com.bjpowernode;
import com.bjpowernode.domain.Student;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMyBatis {
//测试方法,测试功能
@Test
public void testInsert() throws IOException {
//访问mybatis读取student数据
//1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
String config="mybatis.xml";
//2.读取这个config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建了SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
//SqlSession sqlSession = factory.openSession();
SqlSession sqlSession = factory.openSession(true);
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqlId = "com.bjpowernode.dao.StudentDao.insertStudent";
//7. 重要】执行sql语句,通过sqlId找到语句
Student student = new Student();
student.setId(1006);
student.setName("关羽");
student.setEmail("guanyu@163.com");
student.setAge(20);
int nums = sqlSession.insert(sqlId,student);
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
//sqlSession.commit();
//8.输出结果
System.out.println("执行insert的结果="+nums);
//9.关闭SqlSession对象
sqlSession.close();
}
}
传统dao方法的缺陷
package com.bjpowernode.dao.impl;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
public class StudentDaoImpl implements StudentDao {
@Override
public List<Student> selectStudents() {
//获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
String sqlId="com.bjpowernode.dao.StudentDao.selectStudents";
//执行sql语句, 使用SqlSession类的方法
List<Student> students = sqlSession.selectList(sqlId);
//关闭
sqlSession.close();
return students;
}
@Override
public int insertStudent(Student student) {
//获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
String sqlId="com.bjpowernode.dao.StudentDao.insertStudent";
//执行sql语句, 使用SqlSession类的方法
int nums = sqlSession.insert(sqlId,student);
//提交事务
sqlSession.commit();
//关闭
sqlSession.close();
return nums;
}
}
使用传统的dao方法实现每一个操作时,会发现不同的操作中会有很多重复的代码
MyBatis的动态代理分析
package com.bjpowernode;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.dao.impl.StudentDaoImpl;
import com.bjpowernode.domain.Student;
import org.junit.Test;
import java.util.List;
public class TestMyBatis {
@Test
public void testSelectStudents(){
//com.bjpowernode.dao.StudentDao
StudentDao dao = new StudentDaoImpl();
/**
* List<Student> studentList = dao.selectStudents(); 调用
* 1.dao对象,类型是StudentDao,全限定名称是:com.bjpowernode.dao.StudentDao
* 全限定名称 和 namespace 是一样的。
*
* 2.方法名称, selectStudents, 这个方法就是 mapper文件中的 id值 selectStudents
*
* 3.通过dao中方法的返回值也可以确定MyBatis要调用的SqlSession的方法
* 如果返回值是List ,调用的是SqlSession.selectList()方法。
* 如果返回值 int ,或是非List的, 看mapper文件中的 标签是<insert>,<update> 就会调用
* SqlSession的insert, update等方法
*
* mybatis的动态代理: mybatis根据 dao的方法调用,获取执行sql语句的信息。
* mybatis根据你的dao接口,创建出一个dao接口的实现类, 并创建这个类的对象。
* 完成SqlSession调用方法, 访问数据库。
*
*/
List<Student> studentList = dao.selectStudents();
for(Student stu:studentList){
System.out.println(stu);
}
}
@Test
public void testInsertStudent(){
StudentDao dao = new StudentDaoImpl();
Student student = new Student();
student.setId(1005);
student.setName("盾山");
student.setEmail("dunshan@qq.com");
int nums = dao.insertStudent(student);
System.out.println("添加对象的数量:"+nums);
}
}
你的程序不需要创建Dao接口的实现类了,由mybatis根据Dao接口在内部自己把实现类实现了。并且完成Dao类中方法的调用。你在做mybatis操作时只需要把接口提供给它。实现类由mybatis自动做。
Mybatis的动态代理机制
package com.bjpowernode;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import java.util.List;
public class TestMyBatis {
@Test
public void testSelectStudents(){
/**
* 使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口)
* getMapper能获取dao接口对于的实现类对象。
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//com.sun.proxy.$Proxy2 : jdk的动态代理
System.out.println("dao="+dao.getClass().getName());
//调用dao的方法, 执行数据库的操作
List<Student> students = dao.selectStudents();
for(Student stu: students){
System.out.println("学生="+stu);
}
}
@Test
public void testInsertStudent(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setId(1007);
student.setName("李飞");
student.setEmail("dunshan@qq.com");
student.setAge(28);
int nums = dao.insertStudent(student);
sqlSession.commit();
System.out.println("添加对象的数量:"+nums);
}
}
使用动态代理时不要使用重载的方法,因为它就是根据方法名称来唯一区别的
#和$的区别
#{}是一个占位符,在底层是使用PreparedStatement来替换,效率高,安全
${}是字符串替换和拼接,它直接把参数值替换到里面了,底层使用的是Statement,不安全,有sql注入
定义别名
<!--在主配置文件中定义别名-->
<!--定义别名-->
<typeAliases>
<!--
第一种方式:
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<!--<typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
<typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />-->
<!--
第二种方式
<package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
-->
<package name="com.bjpowernode.domain"/>
<package name="com.bjpowernode.vo"/>
</typeAliases>
查询返回Map
<!--返回Map
1)列名是map的key, 列值是map的value
2)只能最多返回一行记录。多余一行是错误
-->
<select id="selectMapById" resultType="java.util.HashMap">
select id,name,email from student where id=#{stuid}
</select>
<!--使用resultMap
1)先定义resultMap
2)在select标签,使用resultMap来引用1定义的。
-->
<!--定义resultMap
id:自定义名称,表示你定义的这个resultMap
type:java类型的全限定名称
-->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
<!--列名和java属性的关系-->
<!--主键列,使用id标签
column :列名
property:java类型的属性名
-->
<id column="id" property="id" />
<!--非主键列,使用result-->
<result column="name" property="name" />
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
select id,name, email , age from student
</select>
</resultMap>
<!--列名和属性名不一样:第一种方式-->
<select id="selectMyStudent" resultMap="myStudentMap">
select id,name, email , age from student
</select>
<!--列名和属性名不一样:第二种方式
resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)
在sql语句中使用列别名,让它和java属性名一致
-->
<select id="selectDiffColProperty" resultType="com.bjpowernode.domain.MyStudent">
select id as stuid ,name as stuname, email as stuemail , age stuage from student
</select>
<!--第一种 like , java代码指定 like的内容-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like #{name}
</select>
<!--第二种方式:在mapper文件中拼接 like的内容-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like "%" #{name} "%"
</select>
实际上这些循环就是和字符串的一些连接,只是把它们连接起来了
SQL代码片段
<!--定义sql片段-->
<sql id="studentSql">
select id,name, age, email from student
</sql>
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
<!--使用sql片段-->
select <include refid="studentSqlOne" /> from student
where id > 0
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
DataSource源码
package javax.sql;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Wrapper;
public interface DataSource extends CommonDataSource, Wrapper {
Connection getConnection() throws SQLException;
Connection getConnection(String username, String password)
throws SQLException;
}
只要实现了DataSource就一定可以获取到连接对象
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>
<!--指定properties文件的位置,从类路径根开始找文件-->
<properties resource="jdbc.properties" />
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--定义别名-->
<typeAliases>
<!--
第一种方式:
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<!--<typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
<typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />-->
<!--
第二种方式
<package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
-->
<package name="com.bjpowernode.domain"/>
<package name="com.bjpowernode.vo"/>
</typeAliases>
<!--配置插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
<environments default="mydev">
<environment id="mydev">
<!--
transactionManager:mybatis提交事务,回滚事务的方式
type: 事务的处理的类型
1)JDBC : 表示mybatis底层是调用JDBC中的Connection对象的,commit, rollback
2)MANAGED : 把mybatis的事务处理委托给其它的容器(一个服务器软件,一个框架(spring))
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
数据源表示连接Connection对象的。(访问数据库的,用来创建连接)
type:指定数据源的类型
1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
3)JNDI:java命名和目录服务(windows注册表)
-->
<dataSource type="POOLED">
<!--连接数据库需要知道数据库的信息-->
<!--数据库的驱动类名-->
<property name="driver" value="${jdbc.driver}"/>
<!--连接数据库的url字符串-->
<property name="url" value="${jdbc.url}"/>
<!--访问数据库的用户名-->
<property name="username" value="${jdbc.user}"/>
<!--密码-->
<property name="password" value="${jdbc.passwd}"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
<!--第一种方式:指定多个mapper文件-->
<!--<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<mapper resource="com/bjpowernode/dao/OrderDao.xml" />-->
<!--第二种方式: 使用包名
name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
使用package的要求:
1. mapper文件名称需要和接口名称一样, 区分大小写的一样
2. mapper文件和dao接口需要在同一目录
-->
<package name="com.bjpowernode.dao"/>
<!-- <package name="com.bjpowernode.dao2"/>
<package name="com.bjpowernode.dao3"/>-->
</mappers>
</configuration>
问题
问题:
The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
服务器时区值“Öйú±ê׼ʱ¼ä”无法识别或代表多个时区。 如果希望利用时区支持,则必须(通过serverTimezone配置属性)配置服务器或JDBC驱动程序,以使用更特定的时区值
解决办法:在连接数据库url的后缀加上?serverTimezone=GMT%2B8
Unknown initial character set index '255' received from server. Initial client character set can be forced via the 'characterEncoding' property.
这个错误可能是mysql的驱动jar包导错了