Hello friend, I'm Ritc|

Ritchie里其

园龄:2年6个月粉丝:4关注:7

MyBatis

概述

1.框架

framework,对通用代码的封装,是提前写好的一堆接口和类。
SSM:Spring + SpringMVC + MyBatis
SpringBoot
SpringCloud

MyBatis就是封装了JDBC

2. 三层框架

Web前端 -Ajax- 表现层
业务层
持久层
数据库

3.JDBC不足

sql语句写死在java程序中,改sql就要改java代码,违背开闭原则OCP;
给?传值繁琐;
将结果集封装到java对象也繁琐。

4.了解ORM思想

MyBatis是对于dao持久层的框架
轻量级
支持动态sql
sql与代码分离

MyBatis是一个半自动ORM(object relation mapping)映射的框架。对象关系映射。
O -> JVM中的Java对象
R -> 关系型数据库
M -> 映射【一个对象<->表中一条记录】
半自动:sql要程序员自己写

官网下载
https://blog.mybatis.org/
官方文档
https://mybatis.net.cn/

入门

1. 建一个空项目

1. New Project
2. Empty Project
3. Project Structure -> Project选择JDK版本
4. Settings -> Maven选择版本以及配置文件和仓库

注意:
如果不显示项目名
关闭idea
删除本地目录中该项目对应的.idea文件
重新打开idea即可

2. 第一个maven项目配置

点住空项目名。右键new Module...
选择Maven模板
右下角:Enable -Auto

<!-- 1.在pom文件中设置打包方式 -->
<packaging>jar</packaging>
<!-- 2.引入相关依赖 -->
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 引入logback依赖,它实现了slf4j规范 -->
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
3. 编写xml核心配置文件,用于配置数据库等
mybatis-config.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">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 指定XxxMapper.xml文件的路径,从resource根路径开始找 -->
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
还有一个XxxMapper.xml文件,专门用来编写sql语句
一般一个表对应一个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">
<!-- namespace是咖啡豆的根路径 -->
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>

3. 目录解释

1.environments ==>表示环境的配置 可以配置多个环境
2.environment id="mysql" 指定是mysql的环境
3.transactionManager 配置事务管理器
它的type有两种
JDBC:表示使用jdbc 的方式来进行事务的管理,底层实例化JdbcTransaction对象
MANAGED:没有做任何操作 依赖于容器 以容器的方式的来进行事务管理,底层实例化ManagedTransaction对象
spring +mybatis ==设置参数MANAGED 表示已容器spring的方式来进行事务的管理
4.dataSource ==>数据源
POOLED ==> 表示一连接池的方式来管理连接 不会反复的创建与销毁连接 ,适用于开发测试环境。
UNPOOLED > 不使用连接池的方式来进行管理连接 使用的时候都创建连接与销毁连接 ,适用于小规模。
JNDI
>必须在web环境,依赖于web容器 在tomcat 中可以进行配置(重点),生产环境优先使用这种。

4. 工具类

4.1 SqlSessionFactoryUtil

public enum SqlSessionFactoryUtil {
// 单例
SSF;
private SqlSessionFactory sqlSessionFactory;
SqlSessionFactoryUtil() {
try {
// 从resources根路径开始的目录
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 定义一个公有的方法返回sqlSessionFactory
*/
public SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
}

4.2 CommentMapper

public class CommentMapper {
public SqlSession sqlSession;
@Before
public void before() {
/* autoCommit是true,就表示没有开启事务,建议空着,开始事务 */
sqlSession = SqlSessionFactoryUtil.SSF.getSqlSessionFactory().openSession(true);
}
@After
public void after() {
//关闭资源
sqlSession.close();
}
}

5. 日志logback

  1. 在pom文件中添加依赖
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
<scope>test</scope>
</dependency>
  1. 引入logback必须的xml配置文件
// 文件名必须是logback.xml或者logback-test.xml,不能是其他名字
// 必须放在类的根路径下,不能是其他位置
<?xml version="1.0" encoding="UTF-8"?>
<!-- 配置文件修改时重新加载,默认true -->
<configuration debug="false">
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder" charset="UTF-8">
<!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- mybatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 日志输出级别,LOGBACK日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR-->
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>

6.老杜版本SqlSessionUtil

public class SqlSessionUtil {
private SqlSessionUtil() {
}
private static SqlSessionFactory sqlSessionFactory;
static {
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 全局的,服务器级别的,一个服务器当中定义一个即可
*/
private static ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();
public static SqlSession openSession() {
SqlSession sqlSession = local.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();
// 将sqlSession绑定到当前线程上,只绑定一次
local.set(sqlSession);
}
return sqlSession;
}
public static void close(SqlSession sqlSession){
if (sqlSession != null) {
sqlSession.close();
// 注意移除SqlSession对象和当前线程的绑定关系
// 因为Tomcat服务器支持线程池
local.remove();
}
}
}

增删改查

{} 相当于JDBC里的问号?

XxxMapper.xml里面的crud语句,注释掉的话,要用<!-- -->

{abc}是去entity类里面找对应的getAbc方法

insert
delete
update
select

namespace是为了防止id冲突,完整的应该写成
sqlSession.方法名(namespace.id)
MyBatis规定namespace必须是dao接口的全限定类名,
if必须是dao接口中的方法名。

dao以后改叫mapper
select标签的resultType是pojo/entity的全限定名

resource都是从根路径开始
增删改查方法有两个参数:
一个是sql语句的id,从XxxMapper.xml中复制过来,另一个是对象,该对象封装了sql语句中的所有占位符参数#{}

XxxDaoImpl中的sqlSession调用的方法,传入参数,如果只有一个参数,那么在XxxMapper.xml中的sql语句里的#{}里可以随便写。
但建议见名知意。
如果是多参数,必须跟实体类Dao对应上。
WEB-INF目录下的web.xml文件
<web-app>标签中的metadata-complete=“false”的时候才是支持注解的,
如果是true,那么serlvet上面是不支持注解的。

批量删除

拼接表名${}

deleted from xx where id in(${})

模糊查询

xxx like “%”#{xxx}“%”

insert

useGeneratedKeys=''true''使用自动生成的主属性
keyProperty="id"指定主键值赋值给对象的哪个属性
insert into xxx values(null,xx,xxx)
就是给表的主属性id自动生成

Java生成类

是一个开源的分析、编辑和创建Java字节码的类库。通过使用Javassist对字节码操作作为JBoss实现动态“AOP”框架。

就不用写DaoImpl类

Javassist使用

引入依赖

<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.28.0-GA</version>
</dependency>

类型别名(typeAliases)

在config文件中,<typeAliases>标签,
里面的type写的是com.xxx.pojo.User
alias写的是自己指定的别名,不区分大小写

注意:
Mybatis核心配置文件是有顺序的!!!

给所有类起别名,使用简明作为别名,不区分大小写。
<package name="com.xxx.pojo">

namespace不能起别名

参数处理

XxxMapper方法里面的参数

Param注解

多参数用这个
eg. User selectUser(@Param("name") String name,@Param("age")int age);

返回Map

返回的数据没有合适的实体类对应,可采用Map集合接收,字段名是key,字段值做value。

返回一个Map<String, Object> selectById(Long id);
返回多个List<Map<String, Object>> selectAll();

在XxxMapper接口上加一个@MapKey("id")

ResultMap封装结果映射

两个结果集id要一致
<resultMap id="结果集id" type="Xxx">
<result property="属性名" column="数据库表名"/>
<result property="属性名" column="数据库表名"/>
</resultMap>
<select id="xxx" resultMap="结果集id">
</select>

开启驼峰命名自动映射

属性名必须遵循Java命名规范

<settings>
<setting name="xxxx" value="true"/>
</settings>

返回总记录条数

count(1)或count(*)都可以
count(字段名)的话会去除null

动态SQL

if标签

<select id="">
select * from table where 1=1
/*
if标签中的test属性是必须的
test值是false或true
如果true则sql语句会拼接,反之不拼接
@Param,有pojo就写属性名
and表示并且,不能使用&&
*/
<if test="uName != null and uName !=''">
and age >= 18;
</if>
<if test="里面是Boolean类型">
and
</if>
</select>

where标签

<select id="">
select * from table
/* where标签可以智能的去掉前面的and,但我们写的时候,and都写上*/
<where>
<if test="uName != null and uName !=''">
and age >= 18;
</if>
<if test="">
and
</if>
</where>
</select>

trim标签

<!-- trim
prefix:加前缀
suffix:加后缀
prefixOverrides:删除前缀
suffixOverrides:删除后缀
-->
<select id="">
select * from table
<trim prefixOverrides="" suffix="" prefix="" suffixOverrides=""></trim>
/*prefix="where" 在trim标签所有内容前加where
suffixOverrides="and|or"把trim标签中内容的后缀and或or去掉
*/
<trim prefix="where" suffixOverrides="and|or">
<if test="uName != null and uName !=''">
hobby like "%"#{hobby}"%" and
</if>
</trim>
</select>

set标签

<!-- set标签
拼接set,可以智能的去掉句尾的,
-->
<update id="">
update table_name
<set>
<if test="">
.....,
</if>
</set>
where
id =#{id}
</update>

choose when otherwise标签

<!-- choose when otherwise -->
<!-- 一般三个标签一起用,保证至少会有一个执行 -->
<!-- 等同于 if , else if ,else if, else-->
<!-- when相当于else if ,otherwise相当于最后的else-->
<select id="">
select * from table_name
<where>
<choose>
<when test="true">
// 前面不用加and
</when>
<otherwise>
</otherwise>
</choose>
</where>
</select>

foreach标签

<!-- foreach
collection:指定数组或集合
item:代表数组或集合中的元素
separator:循环之间的分隔符
open:foreach循环拼接的所有sql语句的最前面以什么开始,eg.(
close:foreach循环拼接的所有sql语句最后面以什么结束,eg.)
这个括号是整个语句前面的,只有一个,循环之外
-->
<select id="deletedByIds">
delete from t where id in(
<foreach collection="" item="" separator=",">
#{aaaa}
</foreach>
)
</select>
<!--批量插入-->
<insert id="">
insert into table_name values
<foreach collection="" item="" separator=",">
(null,#{},#{},#{})
</foreach>
</insert>
<!-- 批量删除 -->
<delete id="">
delete from table_name where
<foreach collection="" item="" separator="or">
id=#{}
</foreach>
</delete>

sql和include标签

<!--sql标签,include标签-->
<sql id="起一个id名">
//重复出现的代码放这里
</sql>
<select id="" resultMap="">
// include到这里就可以引用了
<include refid="起一个id名"></include>
</select>

高级映射,延迟加载

多表间的映射 -- 高级映射

eg.学生表Student班级表Clazz
多个学生对一个班级
如何分主表和副表?
谁在前谁就是主表
多在前多就是主表,一在前依旧是主表

多对一

多是主表

<!--多对一,方式1:一条SQL,级联属性映射-->
<resultMap id="studentResultMap" type="student">
<!--column里面查的值赋给property-->
<id property="sid" column="sid"></id>
<result property="sname" column="sid"/>
<!--clazz是student类里的班级属性-->
<result property="clazz.cid" column="cid"/>
<result property="clazz.cname" column="cname"/>
</resultMap>
<select id="selectById" resultMap="studentResultMap">
select
s.sid, s.sname, c.cid, c.cname
from
/*左外连接就是左表为主表,on后面是条件*/
t_stu s left join t_clz c on s.cid = c.cid
where
s.sid = #{sid}
</select>
<!--多对一,方式二:一条SQL,association-->
<resultMap id="studentResultMapAssociation" type="Studnet">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<!--一个Student关联一个Clazz,javaType用来指定需要映射的java类型-->
<association property="clazz" javaType="Clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
</association>
</resultMap>
<select id="selectByIdAssociation" resultMap="studentResultMapAssociation">
select
s.sid, s.sname, c.cid, c.cname
from
t_stu s left join t_clz c on s.cid = c.cid
where
s.sid = #{sid}
</select>
<!--多对一,方式三:两条SQL分布查询,优点:可复用,支持懒加载-->
<!--延迟加载(懒加载),用的时候载执行查询,不用的时候不查询
实际开发中,一般都会设置全局懒加载,在<setting name="lazyLoadingEnabled" value="true">
-->
<!--两条SQL需要写两个Mapper.xml-->
<resultMap id="studentResultMapByStep" type="">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz"
select=""
column=""
fetchType="eager"/>
<!--fetchType="eager"关闭改查询的懒加载-->
</resultMap>
<select id="" resultMap="studentResultMapByStep">
</select>

一对多

一是主表

<resultMap id="" type="">
<id property="cid" column=""/>
<result property="cname" column="cname"/>
<!-- 一对多 这里用collection
ofType属性用来指定集合当中的元素类型 -->
<collection property="stus" ofType="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
</collection>
</resultMap>
<select id="" resultMap="">
</select>
<!--一对多,方式二-->
<resultMap id="" type="">
<id property="cid" column="cid"></id>
<result property="cname" column="cname">
</result>
<collection property="stus"
select="sql语句id,就是对应接口上的方法,右键copy reference"
column="cid"/>
<!--这里的cid,跟下面select 【cid】 from xxx 要对应-->
</resultMap>
<select id="" resultMap="">
select cid,cname from t_clz where cid=#{cid}
</select>

多对多

分解成两个一对多

缓存Cache

一级缓存:将查询的数据存储到SqlSession中
二级缓存:将查询的数据存储到SqlSessionFactory中
集成第三方缓存:eg.EhCache、MemCache等

缓存只针对DQL语句,也就是说缓存机制只对应select语句

只要执行一次增删改,缓存(包括一二级)就会清空
手动清空一级缓存的方法:sqlSession.clearCache();

默认情况下,MyBatis的二级缓存是开启的

<setting name ="cacheEnable" vlaue="true">全局性开启或关闭所有映射器配置文件中已配置的任何缓存,默认是true,无需设置

使用二级缓存要保证实力类是可序列化的,也就是要实现Serializable接口。
SqlSession对象关闭或提交之后,一级缓存中的数据才会被写入到二级缓存中,此时二级缓存才可用。
在需要使用二级缓存的SqlMapper.xml中添加配置:

<cache/>

集成EhCache

集成第三方缓存是为了代替mybatis自带的二级缓存,一级缓存是无法替代的。

逆向

就是根据数据库表逆向生成Java的POJO类,SqlMapper.xml文件,以及Mapper接口等。
需要借助逆向工程插件。

基础环境搭建

在pom.xml中加入插件依赖

<!--定制构建过程-->
<build>
<!--可配置多个插件-->
<plugins>
<!--其中的一个插件:mybatis逆向工程插件-->
<plugin>
<!--插件的GAV坐标-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.1</version>
<!--允许覆盖-->
<configuration>
<overwrite>true</overwrite>
</configuration>
<!--插件的依赖-->
<dependencies>
<!--mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

在gfneratorConfig.xml中设置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime有两个值:
MyBatis3Simple:生成的是基础版,只有基本的增删改查。
MyBatis3:生成的是增强版,除了基本的增删改查之外还有复杂的增删改查。
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--防止生成重复代码-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<commentGenerator>
<!--是否去掉生成日期-->
<property name="suppressDate" value="true"/>
<!--是否去除注释-->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--连接数据库信息-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/powernode"
userId="root"
password="root">
</jdbcConnection>
<!-- 生成pojo包名和位置 -->
<javaModelGenerator targetPackage="com.powernode.mybatis.pojo" targetProject="src/main/java">
<!--是否开启子包-->
<property name="enableSubPackages" value="true"/>
<!--是否去除字段名的前后空白-->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成SQL映射文件的包名和位置 -->
<sqlMapGenerator targetPackage="com.powernode.mybatis.mapper" targetProject="src/main/resources">
<!--是否开启子包-->
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成Mapper接口的包名和位置 -->
<javaClientGenerator
type="xmlMapper"
targetPackage="com.powernode.mybatis.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 表名和对应的实体类名-->
<table tableName="t_car" domainObjectName="Car"/>
</context>
</generatorConfiguration>

怎么用?

点开右边的maven -> plugins -> mybstis-generator -> mybatis-genrator:generate
双击即可

查一个selectByPrimaryKey
查所有selectByExample

分页PageHelper

limit分页

select * from t_car limit 2;
select * from t_car limit 0,2;
这两个是等效的
第一个数字是开始的下标,第二个是需要显示的记录条数
第一条记录的下标是0

第pageNum页:
limit (pageNum-1)*pageSize, pageSize

PageHelper

官方网站

第一步:引入依赖

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>

第二步:在mybatis-config.xml中配置分页拦截器

<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

第三步:写代码

一定要在DQL语句前,开启分页功能
int pageNum = 2;
int pageSize = 3;
// 开启分页
PageHelper.startPage(pageNum, pageSize);
// 执行查询
mapper.selectAll();
// 获取分页信息,5是代号页码
new PageInfo<>(cars, 5);

注释

在接口类中写,XxxMapper
1.增
@insert(里面写sql)
int insertCar car);
2.删
@Delete(写sql语句)
int deleteByIdLong id);
3.改
@Update(写sql
int update(Car car)
4.查
@Selectsql语句)
@Results({
@Result(property=“id”, column="id"
@Result(property="carNum", column="car_num"
@Result(property="brand", column="brand"
})
Car selectByIdLong id);

Druid连接池

配置pom.xml文件

<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency>

创建DruidDataSourceFactory
MyDruidDataSourceFactory并继承PooledDataSourceFactory,并替换数据源。

public class MyDruidDataSourceFactory extends PooledDataSourceFactory { public MyDruidDataSourceFactory() { this.dataSource = new DruidDataSource();//替换数据源 } }

修改mybatis-config.xml

<dataSource type="com.qf.xxx.utils.DruidDataSourceFactory"><!--数据源工 厂--><property name="driverClass" value="${driver}"/> <property name="jdbcUrl" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>

注意:< property name="属性名" />属性名必须与com.alibaba.druid.pool.DruidAbstractDataSource
中一致。

本文作者:Ritchie里其

本文链接:https://www.cnblogs.com/wang-zeyu/p/16923896.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Ritchie里其  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
✨欢迎你~🍻
✨欢迎你~🍻
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 遥か Aimer
遥か - Aimer
00:00 / 00:00
An audio error has occurred.

作词 : aimerrhythm/田中ユウスケ

作曲 : 田中ユウスケ

编曲 : 玉井健二/百田留衣

海岸線の雨に ちらばった君の影

思い出が交差する 海辺の街

君はあの日のまま いまも夢を見てた

君はあの日のまま いまも夢を見てた

遥か記憶の空 2人照らす光

遥か記憶の空 2人照らす光

膝までの浅瀬で 見つけた星

君まで届くなんてさ ありえないような

浅い眠りの中で 深い夢から覚めて

浅い眠りの中で 深い夢から覚めて

裸足のまま駆けてく まばゆい星

君はあの日のまま どんな夢を見てた?

君はあの日のまま どんな夢を見てた?

遥か記憶の空 2人照らす光

遥か記憶の空 2人照らす光

いつまでもこうして 笑っててほしい

夜空に舞い上がる 幾千の花びら

でたらめな誓いで 生きてく日々

君から届くなんてさ ありえないような