1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.db;
15
16 import java.lang.reflect.InvocationTargetException;
17 import java.lang.reflect.Method;
18 import java.sql.Connection;
19 import java.sql.PreparedStatement;
20 import java.sql.ResultSet;
21 import java.sql.SQLException;
22 import java.sql.Statement;
23
24 import ch.qos.logback.core.UnsynchronizedAppenderBase;
25 import ch.qos.logback.core.db.dialect.DBUtil;
26 import ch.qos.logback.core.db.dialect.SQLDialect;
27 import ch.qos.logback.core.db.dialect.SQLDialectCode;
28
29
30
31
32
33
34 public abstract class DBAppenderBase<E> extends UnsynchronizedAppenderBase<E> {
35
36 protected ConnectionSource connectionSource;
37 protected boolean cnxSupportsGetGeneratedKeys = false;
38 protected boolean cnxSupportsBatchUpdates = false;
39 protected SQLDialect sqlDialect;
40
41 protected abstract Method getGeneratedKeysMethod();
42
43 protected abstract String getInsertSQL();
44
45 @Override
46 public void start() {
47
48 if (connectionSource == null) {
49 throw new IllegalStateException(
50 "DBAppender cannot function without a connection source");
51 }
52
53 sqlDialect = DBUtil
54 .getDialectFromCode(connectionSource.getSQLDialectCode());
55 if (getGeneratedKeysMethod() != null) {
56 cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys();
57 } else {
58 cnxSupportsGetGeneratedKeys = false;
59 }
60 cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates();
61 if (!cnxSupportsGetGeneratedKeys && (sqlDialect == null)) {
62 throw new IllegalStateException(
63 "DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect");
64 }
65
66
67 super.start();
68 }
69
70
71
72
73 public ConnectionSource getConnectionSource() {
74 return connectionSource;
75 }
76
77
78
79
80
81 public void setConnectionSource(ConnectionSource connectionSource) {
82 this.connectionSource = connectionSource;
83 }
84
85 @Override
86 public void append(E eventObject) {
87 Connection connection = null;
88 try {
89 connection = connectionSource.getConnection();
90 connection.setAutoCommit(false);
91 PreparedStatement insertStatement;
92
93 if (cnxSupportsGetGeneratedKeys) {
94 String EVENT_ID_COL_NAME = "EVENT_ID";
95
96 if (connectionSource.getSQLDialectCode() == SQLDialectCode.POSTGRES_DIALECT) {
97 EVENT_ID_COL_NAME = EVENT_ID_COL_NAME.toLowerCase();
98 }
99 insertStatement = connection.prepareStatement(getInsertSQL(),
100 new String[] { EVENT_ID_COL_NAME });
101 } else {
102 insertStatement = connection.prepareStatement(getInsertSQL());
103 }
104
105 long eventId;
106
107 synchronized (this) {
108 subAppend(eventObject, connection, insertStatement);
109 eventId = selectEventId(insertStatement, connection);
110 }
111 secondarySubAppend(eventObject, connection, eventId);
112
113
114 close(insertStatement);
115 insertStatement = null;
116
117 connection.commit();
118 } catch (Throwable sqle) {
119 addError("problem appending event", sqle);
120 } finally {
121 DBHelper.closeConnection(connection);
122 }
123 }
124
125 protected abstract void subAppend(E eventObject, Connection connection,
126 PreparedStatement statement) throws Throwable;
127
128 protected abstract void secondarySubAppend(E eventObject, Connection connection,
129 long eventId) throws Throwable;
130
131 protected long selectEventId(PreparedStatement insertStatement,
132 Connection connection) throws SQLException, InvocationTargetException {
133 ResultSet rs = null;
134 Statement idStatement = null;
135 boolean gotGeneratedKeys = false;
136 if (cnxSupportsGetGeneratedKeys) {
137 try {
138 rs = (ResultSet) getGeneratedKeysMethod().invoke(insertStatement,
139 (Object[]) null);
140 gotGeneratedKeys = true;
141 } catch (InvocationTargetException ex) {
142 Throwable target = ex.getTargetException();
143 if (target instanceof SQLException) {
144 throw (SQLException) target;
145 }
146 throw ex;
147 } catch (IllegalAccessException ex) {
148 addWarn(
149 "IllegalAccessException invoking PreparedStatement.getGeneratedKeys",
150 ex);
151 }
152 }
153
154 if (!gotGeneratedKeys) {
155 idStatement = connection.createStatement();
156 idStatement.setMaxRows(1);
157 String selectInsertIdStr = sqlDialect.getSelectInsertId();
158 rs = idStatement.executeQuery(selectInsertIdStr);
159 }
160
161
162
163 rs.next();
164 long eventId = rs.getLong(1);
165
166 rs.close();
167
168 close(idStatement);
169 idStatement = null;
170
171 return eventId;
172 }
173
174 void close(Statement statement) throws SQLException {
175 if (statement != null) {
176 statement.close();
177 }
178 }
179
180 @Override
181 public void stop() {
182 super.stop();
183 }
184 }