※PK是流水號的問題
首先先創一張表CREATE TABLE CHESS( CHESS_NO NUMBER(10), NAME VARCHAR(10), PRICE NUMBER(5), PRODUCT_DATE DATE, CONSTRAINT CHESS_PK PRIMARY KEY(CHESS_NO) ); CREATE SEQUENCE CHESS_SEQUENCE INCREMENT BY 1 START WITH 1 NOMAXVALUE NOCYCLE CACHE 10; COMMENT ON TABLE CHESS IS '棋表'; COMMENT ON COLUMN CHESS.CHESS_NO IS '棋編號'; COMMENT ON COLUMN CHESS.NAME IS '棋名稱'; COMMENT ON COLUMN CHESS.PRICE IS '棋價錢'; COMMENT ON COLUMN CHESS.PRODUCT_DATE IS '棋的生產日期';
然後增加棋類,欄位對應好,然後給setter/getter,下面是Chess.xml
<insert id="insert" parameterType="Chess">
INSERT INTO CHESS(
<include refid="column" />
)
VALUES(CHESS_SEQUENCE.NEXTVAL, #{name}, #{price}, #{productDate})
</insert>
增加別名時,因為是同一個包,乾脆就增加package就可以了,mybatis會去這個包找,還要記得Chess.xml要設定
<typeAliases> <!-- <typeAlias type="org.mybatis.model.Dept" alias="Dept" /> --> <!-- <typeAlias type="org.mybatis.model.Chess" alias="Chess" /> --> <package name="org.mybatis.model"/> </typeAliases> <!--資料庫操作省略--> <mappers> <mapper resource="org/mybatis/model/Dept.xml" /> <mapper resource="org/mybatis/model/Chess.xml" /> </mappers>
※新增時,PK的問題
這時會發現新增時,PK居然是null System.out.println("----------Chess.insert----------");
Chess chess = new Chess();
chess.setName("五子棋");
chess.setPrice(35);
chess.setProductDate(new Date());
int suc = sqlSession.insert("Chess.insert", chess);
System.out.println("成功新增" + suc + "筆!");
System.out.println("PK=" + chess.getChessNo());
System.out.println("name=" + chess.getName());
System.out.println("price=" + chess.getPrice());
System.out.println("productDate=" + chess.getProductDate());
由於我用的是oracle,所以oracle的解法是這樣
<insert id="insert" parameterType="Chess"> <!-- selectKey因為設定BEFORE,所以會在執行之前,會先執行裡面的語法到setChessNo裡 --> <selectKey keyProperty="chessNo" order="BEFORE" resultType="java.lang.Integer"> SELECT CHESS_SEQUENCE.NEXTVAL FROM DUAL </selectKey> INSERT INTO CHESS( <include refid="column" /> )
以下兩行選擇其一,一般會用第二種
<!--VALUES(CHESS_SEQUENCE.CURRVAL, #{name}, #{price}, #{productDate})-->
VALUES(#{chessNo}, #{name}, #{price}, #{productDate}, #{clazz}, #{score}, #{school})
</insert>
※查詢時,欄位名稱的問題
新增一組PK查詢<select id="getChessById" parameterType="java.lang.Integer" resultType="Chess" >
SELECT
<include refid="column" />
FROM CHESS WHERE CHESS_NO = #{chessNo}
</select>
測試類如下,其實還要增加查不到是null的問題,才不會報Exception,測試就算了
System.out.println("----------Chess.getChessById----------");
Chess chess = sqlSession.selectOne("Chess.getChessById", 12);
System.out.println("chessNo=" + chess.getChessNo());
System.out.println("name=" + chess.getName());
System.out.println("price=" + chess.getPrice());
System.out.println("productDate=" + chess.getProductDate());
此時發現chessNo和productDate是null,因為資料庫有_,java沒有,他把他放到java那裡了,所以可以增加個別名,我最後面剛好是PRODUCT_DATE,所以直接加在後面<select id="getChessById" parameterType="java.lang.Integer" resultType="Chess">
SELECT
<include refid="column" /> as productDate
FROM CHESS WHERE CHESS_NO = #{chessNo}
</select>
但chessNo還是null,因為我沒加別名,但仔細想想,這個做法真是太爛了,一點都不好維護,所以mybatis提供了一個叫resultMap的東西,resultMap和resultType只能選擇其一,做法如下:<resultMap type="Chess" id="ChessInterface">
<result property="chessNo" column="CHESS_NO" />
<result property="productDate" column="PRODUCT_DATE" />
</resultMap>
<select id="getChessById" parameterType="java.lang.Integer" resultMap="ChessInterface" >
SELECT
<include refid="column" />
FROM CHESS WHERE CHESS_NO = #{chessNo}
</select>
type有別名的關係,可以直接寫,id隨便取然後將我們剛剛的resultType改成resultMap,裡面放resultMap的id即可
我目前做的專案都是把全部的屬性打在裡面,像這樣:
<resultMap type="Chess" id="ChessInterface"> <id property="chessNo" column="CHESS_NO" /> <result property="name" column="NAME" /> <result property="price" column="PRICE" /> <result property="productDate" column="PRODUCT_DATE" /> </resultMap>我把PK改成id標籤,結果是一樣的,不過既然是PK,最好就用id,我還試不出差在哪 剛剛第一種做法直接加在欄位後面是不分大小寫的,但property是有分的喔!
還可以用建構子設值,首先在 java bean 的類別裡用工具產生一個所有欄位的建構子,然後xml如下設定(注意順序問題):
<constructor> <idArg column="CHESS_NO" javaType="java.lang.Integer" /> <arg column="NAME" javaType="java.lang.String" /> <arg column="PRICE" javaType="java.lang.Integer" /> <arg column="PRODUCT_DATE" javaType="java.util.Date" /> </constructor>
※jdbcType
預設是 OTHER,這在 Oracle 會不知道如何處理,可以改為 NULL 即可譬如在新增時,欄位是可以 null 的,但 insert 時,還是會報 OTHER 不知道怎麼處理的錯誤,所以可以使用 #{fieldName, jdbcType=NULL}
但如果有很多這樣的東西,可以設定在全域設定這個值,就是在設定資料庫帳密的地方,寫在 properties 同級的下面,如下:
<settings> <setting name="jdbcTypeForNull" value="NULL" /> </settings>
※大小寫要注意
※@Results、@Result、@ResultMap
@Mapper
public interface DeptMapper2 {
@Results(id = "d2", value = {
@Result(id = true, column = "deptno", property = "dno"),
// @Result(column = "dname", property = "name"),
@Result(column = "loc", property = "loc") })
@Select("select * from dept where deptno = #{deptNo}")
public Dept2 getDeptById(int id);
@ResultMap("d2")
@Select("select * from dept")
public List<Dept2> getAllDept2();
}
※使用 @Results 時,不能像 XML一樣單獨定義,其他的方法可以用 @ResultMap 使用,但本身有 @Results 不能再用 @ResultMap
※@Results 寫的地方有差,以此例來說,寫在getAllDept2 上面,那 getDeptById 就算用 @ResultMap 也抓不到
※@SelectProvider
@ResultMap("d2")
@SelectProvider(type = MyProvider.class, method="noParam")
public List<Dept2> providerTest();
@ResultMap("d2")
@SelectProvider(type = MyProvider.class, method="param")
public Dept2 providerTest2(@Param("xxx") int id);
public class MyProvider {
public String noParam() {
return "select * from dept";
}
public static String param(Map<String, Integer> map) {
return "select * from dept where deptno = " + map.get("xxx");
}
}
※使用 @SelectProvider 時,可以用 static,但不能使用 overloading
※有參數時,必須用 Map 接,Key 固定給 String,Value 和資料庫的型態對應好即可,如果怕出錯可給 Object
※@InsertProvider、@DeleteProvider、@UpdateProvider 也差不多
沒有留言:
張貼留言